New routing setup #2395
108 changed files with 855 additions and 1083 deletions
|
@ -59,6 +59,7 @@
|
||||||
"@hot-loader/react-dom": "16.8",
|
"@hot-loader/react-dom": "16.8",
|
||||||
"@lbry/color": "^1.0.2",
|
"@lbry/color": "^1.0.2",
|
||||||
"@lbry/components": "^2.3.3",
|
"@lbry/components": "^2.3.3",
|
||||||
|
"@reach/router": "^1.2.1",
|
||||||
"@types/three": "^0.93.1",
|
"@types/three": "^0.93.1",
|
||||||
"async-exit-hook": "^2.0.1",
|
"async-exit-hook": "^2.0.1",
|
||||||
"babel-eslint": "^10.0.1",
|
"babel-eslint": "^10.0.1",
|
||||||
|
@ -106,8 +107,8 @@
|
||||||
"husky": "^0.14.3",
|
"husky": "^0.14.3",
|
||||||
"json-loader": "^0.5.4",
|
"json-loader": "^0.5.4",
|
||||||
"lbry-format": "https://github.com/lbryio/lbry-format.git",
|
"lbry-format": "https://github.com/lbryio/lbry-format.git",
|
||||||
"lbry-redux": "lbryio/lbry-redux#2a7e05940f892f104428eeb37bd1f178da811a09",
|
"lbry-redux": "lbryio/lbry-redux#86f1340f834d0f5cd5365492a8ff15d4b213a050",
|
||||||
"lbryinc": "lbryio/lbryinc#437260f3dad2321e892388b68749ee6af01aff2b",
|
"lbryinc": "lbryio/lbryinc#d9f9035113c8b9ab3b0ee7ffbd38f910086a665e",
|
||||||
"lint-staged": "^7.0.2",
|
"lint-staged": "^7.0.2",
|
||||||
"localforage": "^1.7.1",
|
"localforage": "^1.7.1",
|
||||||
"make-runnable": "^1.3.6",
|
"make-runnable": "^1.3.6",
|
||||||
|
|
|
@ -35,9 +35,7 @@ export default appState => {
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
const rendererURL = isDev // ? `http://localhost:${process.env.ELECTRON_WEBPACK_WDS_PORT}`
|
const rendererURL = isDev ? `http://localhost:8080` : `file://${__dirname}/index.html`;
|
||||||
? `http://localhost:8080/index.dev.html`
|
|
||||||
: `file://${__dirname}/index.html`;
|
|
||||||
|
|
||||||
let window = new BrowserWindow(windowConfiguration);
|
let window = new BrowserWindow(windowConfiguration);
|
||||||
|
|
||||||
|
|
|
@ -5,4 +5,8 @@ const port = 1337;
|
||||||
|
|
||||||
app.use(express.static(__dirname));
|
app.use(express.static(__dirname));
|
||||||
|
|
||||||
app.listen(port, () => console.log(`UI server listening at localhost://${port}`));
|
app.get('*', function(req, res) {
|
||||||
|
res.sendFile(path.join(__dirname, '/index.html'));
|
||||||
|
});
|
||||||
|
|
||||||
|
app.listen(port, () => console.log(`UI server listening at http://localhost:${port}`));
|
||||||
|
|
|
@ -1,13 +1,6 @@
|
||||||
import { hot } from 'react-hot-loader/root';
|
import { hot } from 'react-hot-loader/root';
|
||||||
import { connect } from 'react-redux';
|
import { connect } from 'react-redux';
|
||||||
import {
|
import { doUpdateBlockHeight, doError } from 'lbry-redux';
|
||||||
selectPageTitle,
|
|
||||||
selectHistoryIndex,
|
|
||||||
selectActiveHistoryEntry,
|
|
||||||
doUpdateBlockHeight,
|
|
||||||
doError,
|
|
||||||
} from 'lbry-redux';
|
|
||||||
import { doRecordScroll } from 'redux/actions/navigation';
|
|
||||||
import { doToggleEnhancedLayout } from 'redux/actions/app';
|
import { doToggleEnhancedLayout } from 'redux/actions/app';
|
||||||
import { selectUser } from 'lbryinc';
|
import { selectUser } from 'lbryinc';
|
||||||
import { selectThemePath } from 'redux/selectors/settings';
|
import { selectThemePath } from 'redux/selectors/settings';
|
||||||
|
@ -15,17 +8,13 @@ import { selectEnhancedLayout } from 'redux/selectors/app';
|
||||||
import App from './view';
|
import App from './view';
|
||||||
|
|
||||||
const select = state => ({
|
const select = state => ({
|
||||||
pageTitle: selectPageTitle(state),
|
|
||||||
user: selectUser(state),
|
user: selectUser(state),
|
||||||
currentStackIndex: selectHistoryIndex(state),
|
|
||||||
currentPageAttributes: selectActiveHistoryEntry(state),
|
|
||||||
theme: selectThemePath(state),
|
theme: selectThemePath(state),
|
||||||
enhancedLayout: selectEnhancedLayout(state),
|
enhancedLayout: selectEnhancedLayout(state),
|
||||||
});
|
});
|
||||||
|
|
||||||
const perform = dispatch => ({
|
const perform = dispatch => ({
|
||||||
alertError: errorList => dispatch(doError(errorList)),
|
alertError: errorList => dispatch(doError(errorList)),
|
||||||
recordScroll: scrollPosition => dispatch(doRecordScroll(scrollPosition)),
|
|
||||||
updateBlockHeight: () => dispatch(doUpdateBlockHeight()),
|
updateBlockHeight: () => dispatch(doUpdateBlockHeight()),
|
||||||
toggleEnhancedLayout: () => dispatch(doToggleEnhancedLayout()),
|
toggleEnhancedLayout: () => dispatch(doToggleEnhancedLayout()),
|
||||||
});
|
});
|
||||||
|
|
|
@ -14,9 +14,6 @@ const TWO_POINT_FIVE_MINUTES = 1000 * 60 * 2.5;
|
||||||
|
|
||||||
type Props = {
|
type Props = {
|
||||||
alertError: (string | {}) => void,
|
alertError: (string | {}) => void,
|
||||||
recordScroll: number => void,
|
|
||||||
currentStackIndex: number,
|
|
||||||
currentPageAttributes: { path: string, scrollY: number },
|
|
||||||
pageTitle: ?string,
|
pageTitle: ?string,
|
||||||
theme: string,
|
theme: string,
|
||||||
updateBlockHeight: () => void,
|
updateBlockHeight: () => void,
|
||||||
|
@ -25,12 +22,6 @@ type Props = {
|
||||||
};
|
};
|
||||||
|
|
||||||
class App extends React.PureComponent<Props> {
|
class App extends React.PureComponent<Props> {
|
||||||
constructor() {
|
|
||||||
super();
|
|
||||||
this.mainContent = undefined;
|
|
||||||
(this: any).scrollListener = this.scrollListener.bind(this);
|
|
||||||
}
|
|
||||||
|
|
||||||
componentWillMount() {
|
componentWillMount() {
|
||||||
const { alertError, theme } = this.props;
|
const { alertError, theme } = this.props;
|
||||||
|
|
||||||
|
@ -47,12 +38,6 @@ class App extends React.PureComponent<Props> {
|
||||||
componentDidMount() {
|
componentDidMount() {
|
||||||
const { updateBlockHeight, toggleEnhancedLayout } = this.props;
|
const { updateBlockHeight, toggleEnhancedLayout } = this.props;
|
||||||
|
|
||||||
const mainContent = document.getElementById('content');
|
|
||||||
this.mainContent = mainContent;
|
|
||||||
if (this.mainContent) {
|
|
||||||
this.mainContent.addEventListener('scroll', throttle(this.scrollListener, 750));
|
|
||||||
}
|
|
||||||
|
|
||||||
ReactModal.setAppElement('#window'); // fuck this
|
ReactModal.setAppElement('#window'); // fuck this
|
||||||
|
|
||||||
this.enhance = new EnhancedLayoutListener(() => toggleEnhancedLayout());
|
this.enhance = new EnhancedLayoutListener(() => toggleEnhancedLayout());
|
||||||
|
@ -63,18 +48,9 @@ class App extends React.PureComponent<Props> {
|
||||||
}, TWO_POINT_FIVE_MINUTES);
|
}, TWO_POINT_FIVE_MINUTES);
|
||||||
}
|
}
|
||||||
|
|
||||||
componentWillReceiveProps(props: Props) {
|
|
||||||
const { pageTitle } = props;
|
|
||||||
this.setTitleFromProps(pageTitle);
|
|
||||||
}
|
|
||||||
|
|
||||||
componentDidUpdate(prevProps: Props) {
|
componentDidUpdate(prevProps: Props) {
|
||||||
const { currentStackIndex: prevStackIndex, theme: prevTheme } = prevProps;
|
const { theme: prevTheme } = prevProps;
|
||||||
const { currentStackIndex, currentPageAttributes, theme } = this.props;
|
const { theme } = this.props;
|
||||||
|
|
||||||
if (this.mainContent && currentStackIndex !== prevStackIndex && currentPageAttributes) {
|
|
||||||
this.mainContent.scrollTop = currentPageAttributes.scrollY || 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (prevTheme !== theme) {
|
if (prevTheme !== theme) {
|
||||||
// $FlowFixMe
|
// $FlowFixMe
|
||||||
|
@ -83,26 +59,9 @@ class App extends React.PureComponent<Props> {
|
||||||
}
|
}
|
||||||
|
|
||||||
componentWillUnmount() {
|
componentWillUnmount() {
|
||||||
if (this.mainContent) {
|
|
||||||
this.mainContent.removeEventListener('scroll', this.scrollListener);
|
|
||||||
}
|
|
||||||
|
|
||||||
this.enhance = null;
|
this.enhance = null;
|
||||||
}
|
}
|
||||||
|
|
||||||
setTitleFromProps = (title: ?string) => {
|
|
||||||
window.document.title = title || 'LBRY';
|
|
||||||
};
|
|
||||||
|
|
||||||
scrollListener() {
|
|
||||||
const { recordScroll } = this.props;
|
|
||||||
|
|
||||||
if (this.mainContent) {
|
|
||||||
recordScroll(this.mainContent.scrollTop);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
mainContent: ?HTMLElement;
|
|
||||||
enhance: ?any;
|
enhance: ?any;
|
||||||
|
|
||||||
render() {
|
render() {
|
||||||
|
|
|
@ -1,12 +1,3 @@
|
||||||
import { connect } from 'react-redux';
|
|
||||||
import { doNavigate } from 'redux/actions/navigation';
|
|
||||||
import Button from './view';
|
import Button from './view';
|
||||||
|
|
||||||
const perform = dispatch => ({
|
export default Button;
|
||||||
doNavigate: (path, params) => dispatch(doNavigate(path, params)),
|
|
||||||
});
|
|
||||||
|
|
||||||
export default connect(
|
|
||||||
null,
|
|
||||||
perform
|
|
||||||
)(Button);
|
|
||||||
|
|
|
@ -2,6 +2,8 @@
|
||||||
import * as React from 'react';
|
import * as React from 'react';
|
||||||
import Icon from 'component/common/icon';
|
import Icon from 'component/common/icon';
|
||||||
import classnames from 'classnames';
|
import classnames from 'classnames';
|
||||||
|
import { Link } from '@reach/router';
|
||||||
|
import { formatLbryUriForWeb } from 'util/uri';
|
||||||
|
|
||||||
type Props = {
|
type Props = {
|
||||||
onClick: ?(any) => any,
|
onClick: ?(any) => any,
|
||||||
|
@ -13,9 +15,6 @@ type Props = {
|
||||||
disabled: ?boolean,
|
disabled: ?boolean,
|
||||||
children: ?React.Node,
|
children: ?React.Node,
|
||||||
navigate: ?string,
|
navigate: ?string,
|
||||||
// TODO: these (nav) should be a reusable type
|
|
||||||
doNavigate: (string, ?any) => void,
|
|
||||||
navigateParams: any,
|
|
||||||
className: ?string,
|
className: ?string,
|
||||||
description: ?string,
|
description: ?string,
|
||||||
type: string,
|
type: string,
|
||||||
|
@ -24,7 +23,7 @@ type Props = {
|
||||||
iconColor?: string,
|
iconColor?: string,
|
||||||
iconSize?: number,
|
iconSize?: number,
|
||||||
constrict: ?boolean, // to shorten the button and ellipsis, only use for links
|
constrict: ?boolean, // to shorten the button and ellipsis, only use for links
|
||||||
selected: ?boolean,
|
activeClass?: string,
|
||||||
};
|
};
|
||||||
|
|
||||||
class Button extends React.PureComponent<Props> {
|
class Button extends React.PureComponent<Props> {
|
||||||
|
@ -43,8 +42,6 @@ class Button extends React.PureComponent<Props> {
|
||||||
disabled,
|
disabled,
|
||||||
children,
|
children,
|
||||||
navigate,
|
navigate,
|
||||||
navigateParams,
|
|
||||||
doNavigate,
|
|
||||||
className,
|
className,
|
||||||
description,
|
description,
|
||||||
button,
|
button,
|
||||||
|
@ -53,7 +50,7 @@ class Button extends React.PureComponent<Props> {
|
||||||
iconColor,
|
iconColor,
|
||||||
iconSize,
|
iconSize,
|
||||||
constrict,
|
constrict,
|
||||||
selected,
|
activeClass,
|
||||||
...otherProps
|
...otherProps
|
||||||
} = this.props;
|
} = this.props;
|
||||||
|
|
||||||
|
@ -64,28 +61,19 @@ class Button extends React.PureComponent<Props> {
|
||||||
},
|
},
|
||||||
button
|
button
|
||||||
? {
|
? {
|
||||||
'button--primary': button === 'primary',
|
'button--primary': button === 'primary',
|
||||||
'button--secondary': button === 'secondary',
|
'button--secondary': button === 'secondary',
|
||||||
'button--alt': button === 'alt',
|
'button--alt': button === 'alt',
|
||||||
'button--danger': button === 'danger',
|
'button--danger': button === 'danger',
|
||||||
'button--inverse': button === 'inverse',
|
'button--inverse': button === 'inverse',
|
||||||
'button--disabled': disabled,
|
'button--disabled': disabled,
|
||||||
'button--link': button === 'link',
|
'button--link': button === 'link',
|
||||||
'button--constrict': constrict,
|
'button--constrict': constrict,
|
||||||
'button--selected': selected,
|
}
|
||||||
}
|
|
||||||
: 'button--no-style',
|
: 'button--no-style',
|
||||||
className
|
className
|
||||||
);
|
);
|
||||||
|
|
||||||
const extendedOnClick =
|
|
||||||
!onClick && navigate
|
|
||||||
? event => {
|
|
||||||
event.stopPropagation();
|
|
||||||
doNavigate(navigate, navigateParams || {});
|
|
||||||
}
|
|
||||||
: onClick;
|
|
||||||
|
|
||||||
const content = (
|
const content = (
|
||||||
<span className="button__content">
|
<span className="button__content">
|
||||||
{icon && <Icon icon={icon} iconColor={iconColor} size={iconSize} />}
|
{icon && <Icon icon={icon} iconColor={iconColor} size={iconSize} />}
|
||||||
|
@ -95,16 +83,43 @@ class Button extends React.PureComponent<Props> {
|
||||||
</span>
|
</span>
|
||||||
);
|
);
|
||||||
|
|
||||||
return href ? (
|
if (href) {
|
||||||
<a className={combinedClassName} href={href} title={title}>
|
return (
|
||||||
|
<a href={href} className={combinedClassName}>
|
||||||
|
{content}
|
||||||
|
</a>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Handle lbry:// uris passed in, or already formatted web urls
|
||||||
|
let path = navigate;
|
||||||
|
if (path) {
|
||||||
|
if (path.startsWith('lbry://')) {
|
||||||
|
path = formatLbryUriForWeb(path);
|
||||||
|
} else if (!path.startsWith('/')) {
|
||||||
|
// Force a leading slash so new paths aren't appended on to the current path
|
||||||
|
path = `/${path}`;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return path ? (
|
||||||
|
<Link
|
||||||
|
to={path}
|
||||||
|
title={title}
|
||||||
|
onClick={e => e.stopPropagation()}
|
||||||
|
getProps={({ isCurrent }) => ({
|
||||||
|
className:
|
||||||
|
isCurrent && activeClass ? `${combinedClassName} ${activeClass}` : combinedClassName,
|
||||||
|
})}
|
||||||
|
>
|
||||||
{content}
|
{content}
|
||||||
</a>
|
</Link>
|
||||||
) : (
|
) : (
|
||||||
<button
|
<button
|
||||||
title={title}
|
title={title}
|
||||||
aria-label={description || label || title}
|
aria-label={description || label || title}
|
||||||
className={combinedClassName}
|
className={combinedClassName}
|
||||||
onClick={extendedOnClick}
|
onClick={onClick}
|
||||||
disabled={disabled}
|
disabled={disabled}
|
||||||
type={type}
|
type={type}
|
||||||
{...otherProps}
|
{...otherProps}
|
||||||
|
|
|
@ -1,11 +1,7 @@
|
||||||
import { connect } from 'react-redux';
|
import { connect } from 'react-redux';
|
||||||
import { doFetchClaimsByChannel } from 'redux/actions/content';
|
import { doFetchClaimsByChannel } from 'redux/actions/content';
|
||||||
import { makeSelectCategoryListUris } from 'redux/selectors/content';
|
import { makeSelectCategoryListUris } from 'redux/selectors/content';
|
||||||
import {
|
import { makeSelectFetchingChannelClaims, doResolveUris } from 'lbry-redux';
|
||||||
makeSelectFetchingChannelClaims,
|
|
||||||
doResolveUris,
|
|
||||||
selectActiveHistoryEntry,
|
|
||||||
} from 'lbry-redux';
|
|
||||||
import { selectShowNsfw } from 'redux/selectors/settings';
|
import { selectShowNsfw } from 'redux/selectors/settings';
|
||||||
import CategoryList from './view';
|
import CategoryList from './view';
|
||||||
|
|
||||||
|
@ -13,7 +9,6 @@ const select = (state, props) => ({
|
||||||
urisInList: makeSelectCategoryListUris(props.uris, props.categoryLink)(state),
|
urisInList: makeSelectCategoryListUris(props.uris, props.categoryLink)(state),
|
||||||
fetching: makeSelectFetchingChannelClaims(props.categoryLink)(state),
|
fetching: makeSelectFetchingChannelClaims(props.categoryLink)(state),
|
||||||
obscureNsfw: !selectShowNsfw(state),
|
obscureNsfw: !selectShowNsfw(state),
|
||||||
currentPageAttributes: selectActiveHistoryEntry(state),
|
|
||||||
});
|
});
|
||||||
|
|
||||||
const perform = dispatch => ({
|
const perform = dispatch => ({
|
||||||
|
|
|
@ -1,12 +1,13 @@
|
||||||
// @flow
|
// @flow
|
||||||
import * as ICONS from 'constants/icons';
|
import * as ICONS from 'constants/icons';
|
||||||
import React, { PureComponent, createRef } from 'react';
|
import React, { PureComponent, createRef } from 'react';
|
||||||
import { normalizeURI } from 'lbry-redux';
|
import { normalizeURI, parseURI } from 'lbry-redux';
|
||||||
import ToolTip from 'component/common/tooltip';
|
import ToolTip from 'component/common/tooltip';
|
||||||
import FileCard from 'component/fileCard';
|
import FileCard from 'component/fileCard';
|
||||||
import Button from 'component/button';
|
import Button from 'component/button';
|
||||||
import SubscribeButton from 'component/subscribeButton';
|
import SubscribeButton from 'component/subscribeButton';
|
||||||
import throttle from 'util/throttle';
|
import throttle from 'util/throttle';
|
||||||
|
import { formatLbryUriForWeb } from 'util/uri';
|
||||||
|
|
||||||
type Props = {
|
type Props = {
|
||||||
category: string,
|
category: string,
|
||||||
|
@ -44,7 +45,7 @@ class CategoryList extends PureComponent<Props, State> {
|
||||||
(this: any).handleScrollNext = this.handleScrollNext.bind(this);
|
(this: any).handleScrollNext = this.handleScrollNext.bind(this);
|
||||||
(this: any).handleScrollPrevious = this.handleScrollPrevious.bind(this);
|
(this: any).handleScrollPrevious = this.handleScrollPrevious.bind(this);
|
||||||
(this: any).handleArrowButtonsOnScroll = this.handleArrowButtonsOnScroll.bind(this);
|
(this: any).handleArrowButtonsOnScroll = this.handleArrowButtonsOnScroll.bind(this);
|
||||||
(this: any).handleResolveOnScroll = this.handleResolveOnScroll.bind(this);
|
// (this: any).handleResolveOnScroll = this.handleResolveOnScroll.bind(this);
|
||||||
|
|
||||||
this.scrollWrapper = createRef();
|
this.scrollWrapper = createRef();
|
||||||
}
|
}
|
||||||
|
@ -75,32 +76,34 @@ class CategoryList extends PureComponent<Props, State> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
componentDidUpdate(prevProps: Props) {
|
// The old lazy loading for home page relied on the navigation reducers copy of the scroll height
|
||||||
const { scrollY: previousScrollY } = prevProps.currentPageAttributes;
|
// Keeping it commented out for now to try and find a better way for better TTI on the homepage
|
||||||
const { scrollY } = this.props.currentPageAttributes;
|
// componentDidUpdate(prevProps: Props) {
|
||||||
|
// const {scrollY: previousScrollY} = prevProps.currentPageAttributes;
|
||||||
|
// const {scrollY} = this.props.currentPageAttributes;
|
||||||
|
|
||||||
if (scrollY > previousScrollY) {
|
// if(scrollY > previousScrollY) {
|
||||||
this.handleResolveOnScroll();
|
// this.handleResolveOnScroll();
|
||||||
}
|
// }
|
||||||
}
|
// }
|
||||||
|
|
||||||
handleResolveOnScroll() {
|
// handleResolveOnScroll() {
|
||||||
const {
|
// const {
|
||||||
urisInList,
|
// urisInList,
|
||||||
resolveUris,
|
// resolveUris,
|
||||||
currentPageAttributes: { scrollY },
|
// currentPageAttributes: {scrollY},
|
||||||
} = this.props;
|
// } = this.props;
|
||||||
|
|
||||||
const scrollWrapper = this.scrollWrapper.current;
|
// const scrollWrapper = this.scrollWrapper.current;
|
||||||
if (!scrollWrapper) {
|
// if(!scrollWrapper) {
|
||||||
return;
|
// return;
|
||||||
}
|
// }
|
||||||
|
|
||||||
const shouldResolve = window.innerHeight > scrollWrapper.offsetTop - scrollY;
|
// const shouldResolve = window.innerHeight > scrollWrapper.offsetTop - scrollY;
|
||||||
if (shouldResolve && urisInList) {
|
// if(shouldResolve && urisInList) {
|
||||||
resolveUris(urisInList);
|
// resolveUris(urisInList);
|
||||||
}
|
// }
|
||||||
}
|
// }
|
||||||
|
|
||||||
handleArrowButtonsOnScroll() {
|
handleArrowButtonsOnScroll() {
|
||||||
// Determine if the arrow buttons should be disabled
|
// Determine if the arrow buttons should be disabled
|
||||||
|
@ -261,6 +264,11 @@ class CategoryList extends PureComponent<Props, State> {
|
||||||
const isCommunityTopBids = category.match(/^community/i);
|
const isCommunityTopBids = category.match(/^community/i);
|
||||||
const showScrollButtons = isCommunityTopBids ? !obscureNsfw : true;
|
const showScrollButtons = isCommunityTopBids ? !obscureNsfw : true;
|
||||||
|
|
||||||
|
let channelLink;
|
||||||
|
if (categoryLink) {
|
||||||
|
channelLink = formatLbryUriForWeb(categoryLink);
|
||||||
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<section className="media-group--row">
|
<section className="media-group--row">
|
||||||
<header className="media-group__header">
|
<header className="media-group__header">
|
||||||
|
@ -268,11 +276,7 @@ class CategoryList extends PureComponent<Props, State> {
|
||||||
{categoryLink ? (
|
{categoryLink ? (
|
||||||
<div className="channel-info__actions">
|
<div className="channel-info__actions">
|
||||||
<div className="channel-info__actions__group">
|
<div className="channel-info__actions__group">
|
||||||
<Button
|
<Button label={category} navigate={channelLink} />
|
||||||
label={category}
|
|
||||||
navigate="/show"
|
|
||||||
navigateParams={{ uri: categoryLink, page: 1 }}
|
|
||||||
/>
|
|
||||||
<SubscribeButton
|
<SubscribeButton
|
||||||
button="alt"
|
button="alt"
|
||||||
showSnackBarOnSubscribe
|
showSnackBarOnSubscribe
|
||||||
|
@ -313,7 +317,7 @@ class CategoryList extends PureComponent<Props, State> {
|
||||||
{__(
|
{__(
|
||||||
'The community top bids section is only visible if you allow mature content in the app. You can change your content viewing preferences'
|
'The community top bids section is only visible if you allow mature content in the app. You can change your content viewing preferences'
|
||||||
)}{' '}
|
)}{' '}
|
||||||
<Button button="link" navigate="/settings" label={__('here')} />.
|
<Button button="link" navigate="/$/settings" label={__('here')} />.
|
||||||
</p>
|
</p>
|
||||||
) : (
|
) : (
|
||||||
<ul className="media-scrollhouse" ref={this.scrollWrapper}>
|
<ul className="media-scrollhouse" ref={this.scrollWrapper}>
|
||||||
|
|
|
@ -5,7 +5,6 @@ import {
|
||||||
makeSelectIsUriResolving,
|
makeSelectIsUriResolving,
|
||||||
makeSelectTotalItemsForChannel,
|
makeSelectTotalItemsForChannel,
|
||||||
} from 'lbry-redux';
|
} from 'lbry-redux';
|
||||||
import { doNavigate } from 'redux/actions/navigation';
|
|
||||||
import ChannelTile from './view';
|
import ChannelTile from './view';
|
||||||
|
|
||||||
const select = (state, props) => ({
|
const select = (state, props) => ({
|
||||||
|
@ -15,7 +14,6 @@ const select = (state, props) => ({
|
||||||
});
|
});
|
||||||
|
|
||||||
const perform = dispatch => ({
|
const perform = dispatch => ({
|
||||||
navigate: (path, params) => dispatch(doNavigate(path, params)),
|
|
||||||
resolveUri: uri => dispatch(doResolveUri(uri)),
|
resolveUri: uri => dispatch(doResolveUri(uri)),
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
|
@ -5,6 +5,8 @@ import TruncatedText from 'component/common/truncated-text';
|
||||||
import classnames from 'classnames';
|
import classnames from 'classnames';
|
||||||
import SubscribeButton from 'component/subscribeButton';
|
import SubscribeButton from 'component/subscribeButton';
|
||||||
import type { Claim } from 'types/claim';
|
import type { Claim } from 'types/claim';
|
||||||
|
import { navigate } from '@reach/router';
|
||||||
|
import { formatLbryUriForWeb } from 'util/uri';
|
||||||
|
|
||||||
type Props = {
|
type Props = {
|
||||||
uri: string,
|
uri: string,
|
||||||
|
@ -13,7 +15,6 @@ type Props = {
|
||||||
size: string,
|
size: string,
|
||||||
claim: ?Claim,
|
claim: ?Claim,
|
||||||
resolveUri: string => void,
|
resolveUri: string => void,
|
||||||
navigate: (string, ?{}) => void,
|
|
||||||
};
|
};
|
||||||
|
|
||||||
class ChannelTile extends React.PureComponent<Props> {
|
class ChannelTile extends React.PureComponent<Props> {
|
||||||
|
@ -36,7 +37,7 @@ class ChannelTile extends React.PureComponent<Props> {
|
||||||
}
|
}
|
||||||
|
|
||||||
render() {
|
render() {
|
||||||
const { claim, navigate, isResolvingUri, totalItems, uri, size } = this.props;
|
const { claim, isResolvingUri, totalItems, uri, size } = this.props;
|
||||||
|
|
||||||
let channelName;
|
let channelName;
|
||||||
let subscriptionUri;
|
let subscriptionUri;
|
||||||
|
@ -45,7 +46,7 @@ class ChannelTile extends React.PureComponent<Props> {
|
||||||
subscriptionUri = `lbry://${claim.permanent_url}`;
|
subscriptionUri = `lbry://${claim.permanent_url}`;
|
||||||
}
|
}
|
||||||
|
|
||||||
const onClick = () => navigate('/show', { uri, page: 1 });
|
const onClick = () => navigate(formatLbryUriForWeb(uri));
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<section
|
<section
|
||||||
|
|
|
@ -26,7 +26,7 @@ class FileExporter extends React.PureComponent<Props> {
|
||||||
|
|
||||||
constructor() {
|
constructor() {
|
||||||
super();
|
super();
|
||||||
this.handleButtonClick = this.handleButtonClick.bind(this);
|
(this: any).handleButtonClick = this.handleButtonClick.bind(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
handleFileCreation(filename: string, data: any) {
|
handleFileCreation(filename: string, data: any) {
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
// @flow
|
// @flow
|
||||||
import * as ICONS from 'constants/icons';
|
import * as ICONS from 'constants/icons';
|
||||||
import React from 'react';
|
import React, { Fragment } from 'react';
|
||||||
|
|
||||||
type IconProps = {
|
type IconProps = {
|
||||||
size: number,
|
size: number,
|
||||||
|
@ -16,7 +16,7 @@ const buildIcon = iconStrokes => (props: IconProps) => {
|
||||||
viewBox="0 0 24 24"
|
viewBox="0 0 24 24"
|
||||||
width={size}
|
width={size}
|
||||||
height={size}
|
height={size}
|
||||||
fill="none"
|
fill="solid"
|
||||||
stroke={color}
|
stroke={color}
|
||||||
strokeWidth="2"
|
strokeWidth="2"
|
||||||
strokeLinecap="round"
|
strokeLinecap="round"
|
||||||
|
@ -114,4 +114,16 @@ 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(
|
||||||
|
<Fragment>
|
||||||
|
<path
|
||||||
|
transform="scale(0.15)"
|
||||||
|
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
|
||||||
|
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>
|
||||||
|
),
|
||||||
};
|
};
|
||||||
|
|
|
@ -46,7 +46,8 @@ class IconComponent extends React.PureComponent<Props> {
|
||||||
render() {
|
render() {
|
||||||
const { icon, tooltip, iconColor, size } = this.props;
|
const { icon, tooltip, iconColor, size } = this.props;
|
||||||
const Icon = customIcons[this.props.icon] || FeatherIcons[this.props.icon];
|
const Icon = customIcons[this.props.icon] || FeatherIcons[this.props.icon];
|
||||||
|
console.log('icon', icon);
|
||||||
|
console.log('Icon', Icon);
|
||||||
if (!Icon) {
|
if (!Icon) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
|
@ -45,7 +45,7 @@ export default class ErrorBoundary extends React.Component<Props, State> {
|
||||||
button="link"
|
button="link"
|
||||||
className="load-screen__button"
|
className="load-screen__button"
|
||||||
label={__('refreshing the app')}
|
label={__('refreshing the app')}
|
||||||
onClick={() => window.location.reload()}
|
onClick={() => (window.location.href = '/')}
|
||||||
/>{' '}
|
/>{' '}
|
||||||
{__('to fix it')}.
|
{__('to fix it')}.
|
||||||
</p>
|
</p>
|
||||||
|
|
|
@ -1,11 +1,9 @@
|
||||||
import { connect } from 'react-redux';
|
import { connect } from 'react-redux';
|
||||||
import { doOpenModal } from 'redux/actions/app';
|
import { doOpenModal } from 'redux/actions/app';
|
||||||
import { doNavigate } from 'redux/actions/navigation';
|
|
||||||
import ExternalLink from './view';
|
import ExternalLink from './view';
|
||||||
|
|
||||||
const select = () => ({});
|
const select = () => ({});
|
||||||
const perform = dispatch => ({
|
const perform = dispatch => ({
|
||||||
navigate: (path, params) => dispatch(doNavigate(path, params)),
|
|
||||||
openModal: (modal, props) => dispatch(doOpenModal(modal, props)),
|
openModal: (modal, props) => dispatch(doOpenModal(modal, props)),
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
|
@ -4,6 +4,7 @@ import * as ICONS from 'constants/icons';
|
||||||
import * as React from 'react';
|
import * as React from 'react';
|
||||||
import { isURIValid } from 'lbry-redux';
|
import { isURIValid } from 'lbry-redux';
|
||||||
import Button from 'component/button';
|
import Button from 'component/button';
|
||||||
|
import { navigate } from '@reach/router';
|
||||||
|
|
||||||
type Props = {
|
type Props = {
|
||||||
href: string,
|
href: string,
|
||||||
|
@ -45,14 +46,7 @@ class ExternalLink extends React.PureComponent<Props> {
|
||||||
|
|
||||||
// Return local link if protocol is lbry uri
|
// Return local link if protocol is lbry uri
|
||||||
if (protocol && protocol[0] === 'lbry:' && isURIValid(href)) {
|
if (protocol && protocol[0] === 'lbry:' && isURIValid(href)) {
|
||||||
element = (
|
element = <Button button="link" title={title || href} label={children} navigate={href} />;
|
||||||
<Button
|
|
||||||
button="link"
|
|
||||||
title={title || href}
|
|
||||||
label={children}
|
|
||||||
onClick={() => navigate('/show', { uri: href })}
|
|
||||||
/>
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return element;
|
return element;
|
||||||
|
|
|
@ -9,7 +9,6 @@ import {
|
||||||
makeSelectClaimIsPending,
|
makeSelectClaimIsPending,
|
||||||
} from 'lbry-redux';
|
} from 'lbry-redux';
|
||||||
import { selectRewardContentClaimIds } from 'lbryinc';
|
import { selectRewardContentClaimIds } from 'lbryinc';
|
||||||
import { doNavigate } from 'redux/actions/navigation';
|
|
||||||
import { makeSelectContentPositionForUri } from 'redux/selectors/content';
|
import { makeSelectContentPositionForUri } from 'redux/selectors/content';
|
||||||
import { selectShowNsfw } from 'redux/selectors/settings';
|
import { selectShowNsfw } from 'redux/selectors/settings';
|
||||||
import { makeSelectIsSubscribed, makeSelectIsNew } from 'redux/selectors/subscriptions';
|
import { makeSelectIsSubscribed, makeSelectIsNew } from 'redux/selectors/subscriptions';
|
||||||
|
@ -31,7 +30,6 @@ const select = (state, props) => ({
|
||||||
});
|
});
|
||||||
|
|
||||||
const perform = dispatch => ({
|
const perform = dispatch => ({
|
||||||
navigate: (path, params) => dispatch(doNavigate(path, params)),
|
|
||||||
resolveUri: uri => dispatch(doResolveUri(uri)),
|
resolveUri: uri => dispatch(doResolveUri(uri)),
|
||||||
clearHistoryUri: uri => dispatch(doClearContentHistoryUri(uri)),
|
clearHistoryUri: uri => dispatch(doClearContentHistoryUri(uri)),
|
||||||
});
|
});
|
||||||
|
|
|
@ -11,13 +11,14 @@ import classnames from 'classnames';
|
||||||
import FilePrice from 'component/filePrice';
|
import FilePrice from 'component/filePrice';
|
||||||
import { openCopyLinkMenu } from 'util/context-menu';
|
import { openCopyLinkMenu } from 'util/context-menu';
|
||||||
import DateTime from 'component/dateTime';
|
import DateTime from 'component/dateTime';
|
||||||
|
import { navigate } from '@reach/router';
|
||||||
|
import { formatLbryUriForWeb } from 'util/uri';
|
||||||
|
|
||||||
type Props = {
|
type Props = {
|
||||||
uri: string,
|
uri: string,
|
||||||
claim: ?Claim,
|
claim: ?Claim,
|
||||||
fileInfo: ?{},
|
fileInfo: ?{},
|
||||||
metadata: ?Metadata,
|
metadata: ?Metadata,
|
||||||
navigate: (string, ?{}) => void,
|
|
||||||
rewardedContentClaimIds: Array<string>,
|
rewardedContentClaimIds: Array<string>,
|
||||||
obscureNsfw: boolean,
|
obscureNsfw: boolean,
|
||||||
claimIsMine: boolean,
|
claimIsMine: boolean,
|
||||||
|
@ -61,7 +62,6 @@ class FileCard extends React.PureComponent<Props> {
|
||||||
claim,
|
claim,
|
||||||
fileInfo,
|
fileInfo,
|
||||||
metadata,
|
metadata,
|
||||||
navigate,
|
|
||||||
rewardedContentClaimIds,
|
rewardedContentClaimIds,
|
||||||
obscureNsfw,
|
obscureNsfw,
|
||||||
claimIsMine,
|
claimIsMine,
|
||||||
|
@ -108,11 +108,16 @@ class FileCard extends React.PureComponent<Props> {
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const onClick = e => {
|
||||||
|
e.stopPropagation();
|
||||||
|
navigate(formatLbryUriForWeb(uri));
|
||||||
|
};
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<li
|
<li
|
||||||
tabIndex="0"
|
tabIndex="0"
|
||||||
role="button"
|
role="button"
|
||||||
onClick={!pending ? () => navigate('/show', { uri }) : () => {}}
|
onClick={!pending && claim ? onClick : () => {}}
|
||||||
className={classnames('media-card', {
|
className={classnames('media-card', {
|
||||||
'card--link': !pending,
|
'card--link': !pending,
|
||||||
'media--pending': pending,
|
'media--pending': pending,
|
||||||
|
|
|
@ -21,7 +21,6 @@ class FileListSearch extends React.PureComponent<Props> {
|
||||||
<React.Fragment>
|
<React.Fragment>
|
||||||
<div className="search__results">
|
<div className="search__results">
|
||||||
<section className="search__results-section">
|
<section className="search__results-section">
|
||||||
<div className="search__results-title">{__('Search Results')}</div>
|
|
||||||
<HiddenNsfwClaims uris={uris} />
|
<HiddenNsfwClaims uris={uris} />
|
||||||
{!isSearching && uris && uris.length ? (
|
{!isSearching && uris && uris.length ? (
|
||||||
uris.map(uri =>
|
uris.map(uri =>
|
||||||
|
|
|
@ -9,7 +9,6 @@ import {
|
||||||
} from 'lbry-redux';
|
} from 'lbry-redux';
|
||||||
import { selectRewardContentClaimIds } from 'lbryinc';
|
import { selectRewardContentClaimIds } from 'lbryinc';
|
||||||
import { selectShowNsfw } from 'redux/selectors/settings';
|
import { selectShowNsfw } from 'redux/selectors/settings';
|
||||||
import { doNavigate } from 'redux/actions/navigation';
|
|
||||||
import { doClearPublish, doUpdatePublishForm } from 'redux/actions/publish';
|
import { doClearPublish, doUpdatePublishForm } from 'redux/actions/publish';
|
||||||
import { makeSelectIsSubscribed, makeSelectIsNew } from 'redux/selectors/subscriptions';
|
import { makeSelectIsSubscribed, makeSelectIsNew } from 'redux/selectors/subscriptions';
|
||||||
import FileTile from './view';
|
import FileTile from './view';
|
||||||
|
@ -28,7 +27,6 @@ const select = (state, props) => ({
|
||||||
|
|
||||||
const perform = dispatch => ({
|
const perform = dispatch => ({
|
||||||
clearPublish: () => dispatch(doClearPublish()),
|
clearPublish: () => dispatch(doClearPublish()),
|
||||||
navigate: (path, params) => dispatch(doNavigate(path, params)),
|
|
||||||
resolveUri: uri => dispatch(doResolveUri(uri)),
|
resolveUri: uri => dispatch(doResolveUri(uri)),
|
||||||
updatePublishForm: value => dispatch(doUpdatePublishForm(value)),
|
updatePublishForm: value => dispatch(doUpdatePublishForm(value)),
|
||||||
});
|
});
|
||||||
|
|
|
@ -12,6 +12,8 @@ import FilePrice from 'component/filePrice';
|
||||||
import UriIndicator from 'component/uriIndicator';
|
import UriIndicator from 'component/uriIndicator';
|
||||||
import DateTime from 'component/dateTime';
|
import DateTime from 'component/dateTime';
|
||||||
import Yrbl from 'component/yrbl';
|
import Yrbl from 'component/yrbl';
|
||||||
|
import { navigate } from '@reach/router';
|
||||||
|
import { formatLbryUriForWeb } from 'util/uri';
|
||||||
|
|
||||||
type Props = {
|
type Props = {
|
||||||
obscureNsfw: boolean,
|
obscureNsfw: boolean,
|
||||||
|
@ -23,7 +25,6 @@ type Props = {
|
||||||
claim: ?Claim,
|
claim: ?Claim,
|
||||||
metadata: ?Metadata,
|
metadata: ?Metadata,
|
||||||
resolveUri: string => void,
|
resolveUri: string => void,
|
||||||
navigate: (string, ?{}) => void,
|
|
||||||
clearPublish: () => void,
|
clearPublish: () => void,
|
||||||
updatePublishForm: ({}) => void,
|
updatePublishForm: ({}) => void,
|
||||||
hideNoResult: boolean, // don't show the tile if there is no claim at this uri
|
hideNoResult: boolean, // don't show the tile if there is no claim at this uri
|
||||||
|
@ -83,7 +84,6 @@ class FileTile extends React.PureComponent<Props> {
|
||||||
claim,
|
claim,
|
||||||
metadata,
|
metadata,
|
||||||
isResolvingUri,
|
isResolvingUri,
|
||||||
navigate,
|
|
||||||
obscureNsfw,
|
obscureNsfw,
|
||||||
claimIsMine,
|
claimIsMine,
|
||||||
clearPublish,
|
clearPublish,
|
||||||
|
@ -115,7 +115,7 @@ class FileTile extends React.PureComponent<Props> {
|
||||||
return displayHiddenMessage ? (
|
return displayHiddenMessage ? (
|
||||||
<span className="help">
|
<span className="help">
|
||||||
{__('This file is hidden because it is marked NSFW. Update your')}{' '}
|
{__('This file is hidden because it is marked NSFW. Update your')}{' '}
|
||||||
<Button button="link" navigate="/settings" label={__('content viewing preferences')} />{' '}
|
<Button button="link" navigate="/$/settings" label={__('content viewing preferences')} />{' '}
|
||||||
{__('to see it')}.
|
{__('to see it')}.
|
||||||
</span>
|
</span>
|
||||||
) : null;
|
) : null;
|
||||||
|
@ -136,9 +136,9 @@ class FileTile extends React.PureComponent<Props> {
|
||||||
|
|
||||||
const wrapperProps = name
|
const wrapperProps = name
|
||||||
? {
|
? {
|
||||||
onClick: () => navigate('/show', { uri }),
|
onClick: () => navigate(formatLbryUriForWeb(uri)),
|
||||||
role: 'button',
|
role: 'button',
|
||||||
}
|
}
|
||||||
: {};
|
: {};
|
||||||
|
|
||||||
return !name && hideNoResult ? null : (
|
return !name && hideNoResult ? null : (
|
||||||
|
|
|
@ -3,7 +3,6 @@ import * as settings from 'constants/settings';
|
||||||
import { doChangeVolume } from 'redux/actions/app';
|
import { doChangeVolume } from 'redux/actions/app';
|
||||||
import { selectVolume } from 'redux/selectors/app';
|
import { selectVolume } from 'redux/selectors/app';
|
||||||
import { doPlayUri, doSetPlayingUri, savePosition } from 'redux/actions/content';
|
import { doPlayUri, doSetPlayingUri, savePosition } from 'redux/actions/content';
|
||||||
import { doNavigate } from 'redux/actions/navigation';
|
|
||||||
import { doClaimEligiblePurchaseRewards, makeSelectCostInfoForUri } from 'lbryinc';
|
import { doClaimEligiblePurchaseRewards, makeSelectCostInfoForUri } from 'lbryinc';
|
||||||
import {
|
import {
|
||||||
makeSelectMetadataForUri,
|
makeSelectMetadataForUri,
|
||||||
|
@ -45,7 +44,6 @@ const perform = dispatch => ({
|
||||||
claimRewards: () => dispatch(doClaimEligiblePurchaseRewards()),
|
claimRewards: () => dispatch(doClaimEligiblePurchaseRewards()),
|
||||||
savePosition: (claimId, outpoint, position) =>
|
savePosition: (claimId, outpoint, position) =>
|
||||||
dispatch(savePosition(claimId, outpoint, position)),
|
dispatch(savePosition(claimId, outpoint, position)),
|
||||||
navigate: (path, params) => dispatch(doNavigate(path, params)),
|
|
||||||
});
|
});
|
||||||
|
|
||||||
export default connect(
|
export default connect(
|
||||||
|
|
|
@ -1,7 +1,6 @@
|
||||||
import { connect } from 'react-redux';
|
import { connect } from 'react-redux';
|
||||||
import { selectBalance, selectIsBackDisabled, selectIsForwardDisabled } from 'lbry-redux';
|
import { selectBalance } from 'lbry-redux';
|
||||||
import { formatCredits } from 'util/format-credits';
|
import { formatCredits } from 'util/format-credits';
|
||||||
import { doNavigate, doHistoryBack, doHistoryForward } from 'redux/actions/navigation';
|
|
||||||
import { selectIsUpgradeAvailable, selectAutoUpdateDownloaded } from 'redux/selectors/app';
|
import { selectIsUpgradeAvailable, selectAutoUpdateDownloaded } from 'redux/selectors/app';
|
||||||
import { doDownloadUpgradeRequested } from 'redux/actions/app';
|
import { doDownloadUpgradeRequested } from 'redux/actions/app';
|
||||||
import Header from './view';
|
import Header from './view';
|
||||||
|
@ -11,15 +10,10 @@ const select = state => ({
|
||||||
balance: selectBalance(state),
|
balance: selectBalance(state),
|
||||||
isUpgradeAvailable: selectIsUpgradeAvailable(state),
|
isUpgradeAvailable: selectIsUpgradeAvailable(state),
|
||||||
roundedBalance: formatCredits(selectBalance(state) || 0, 2),
|
roundedBalance: formatCredits(selectBalance(state) || 0, 2),
|
||||||
isBackDisabled: selectIsBackDisabled(state),
|
|
||||||
isForwardDisabled: selectIsForwardDisabled(state),
|
|
||||||
});
|
});
|
||||||
|
|
||||||
const perform = dispatch => ({
|
const perform = dispatch => ({
|
||||||
downloadUpgradeRequested: () => dispatch(doDownloadUpgradeRequested()),
|
downloadUpgradeRequested: () => dispatch(doDownloadUpgradeRequested()),
|
||||||
navigate: path => dispatch(doNavigate(path)),
|
|
||||||
back: () => dispatch(doHistoryBack()),
|
|
||||||
forward: () => dispatch(doHistoryForward()),
|
|
||||||
});
|
});
|
||||||
|
|
||||||
export default connect(
|
export default connect(
|
||||||
|
|
|
@ -15,7 +15,6 @@ type Props = {
|
||||||
back: () => void,
|
back: () => void,
|
||||||
forward: () => void,
|
forward: () => void,
|
||||||
downloadUpgradeRequested: any => void,
|
downloadUpgradeRequested: any => void,
|
||||||
navigate: any => void,
|
|
||||||
};
|
};
|
||||||
|
|
||||||
const Header = (props: Props) => {
|
const Header = (props: Props) => {
|
||||||
|
@ -24,7 +23,6 @@ const Header = (props: Props) => {
|
||||||
balance,
|
balance,
|
||||||
downloadUpgradeRequested,
|
downloadUpgradeRequested,
|
||||||
isUpgradeAvailable,
|
isUpgradeAvailable,
|
||||||
navigate,
|
|
||||||
roundedBalance,
|
roundedBalance,
|
||||||
back,
|
back,
|
||||||
isBackDisabled,
|
isBackDisabled,
|
||||||
|
@ -38,6 +36,7 @@ const Header = (props: Props) => {
|
||||||
return (
|
return (
|
||||||
<header className="header">
|
<header className="header">
|
||||||
<div className="header__navigation">
|
<div className="header__navigation">
|
||||||
|
{/* @if TARGET='app' */}
|
||||||
<Button
|
<Button
|
||||||
className="header__navigation-item header__navigation-item--wallet"
|
className="header__navigation-item header__navigation-item--wallet"
|
||||||
description={__('Your wallet')}
|
description={__('Your wallet')}
|
||||||
|
@ -48,25 +47,23 @@ const Header = (props: Props) => {
|
||||||
<LbcSymbol />
|
<LbcSymbol />
|
||||||
</React.Fragment>
|
</React.Fragment>
|
||||||
}
|
}
|
||||||
onClick={() => navigate('/wallet')}
|
navigate="/$/wallet"
|
||||||
/>
|
/>
|
||||||
|
|
||||||
<Button
|
<Button
|
||||||
className="header__navigation-item header__navigation-item--back"
|
className="header__navigation-item header__navigation-item--back"
|
||||||
description={__('Navigate back')}
|
description={__('Navigate back')}
|
||||||
disabled={isBackDisabled}
|
onClick={() => window.history.back()}
|
||||||
icon={ICONS.ARROW_LEFT}
|
icon={ICONS.ARROW_LEFT}
|
||||||
iconSize={15}
|
iconSize={15}
|
||||||
onClick={back}
|
|
||||||
/>
|
/>
|
||||||
|
|
||||||
<Button
|
<Button
|
||||||
className="header__navigation-item header__navigation-item--forward"
|
className="header__navigation-item header__navigation-item--forward"
|
||||||
description={__('Navigate forward')}
|
description={__('Navigate forward')}
|
||||||
disabled={isForwardDisabled}
|
onClick={() => window.history.forward()}
|
||||||
icon={ICONS.ARROW_RIGHT}
|
icon={ICONS.ARROW_RIGHT}
|
||||||
iconSize={15}
|
iconSize={15}
|
||||||
onClick={forward}
|
|
||||||
/>
|
/>
|
||||||
|
|
||||||
<Button
|
<Button
|
||||||
|
@ -74,8 +71,17 @@ const Header = (props: Props) => {
|
||||||
description={__('Home')}
|
description={__('Home')}
|
||||||
icon={ICONS.HOME}
|
icon={ICONS.HOME}
|
||||||
iconSize={15}
|
iconSize={15}
|
||||||
onClick={() => navigate('/discover')}
|
navigate="/"
|
||||||
/>
|
/>
|
||||||
|
{/* @endif */}
|
||||||
|
{/* @if TARGET='web' */}
|
||||||
|
<Button
|
||||||
|
className="header__navigation-item header__navigation-item--lbry"
|
||||||
|
label={__('LBRY')}
|
||||||
|
iconRight={ICONS.LBRY}
|
||||||
|
navigate="/"
|
||||||
|
/>
|
||||||
|
{/* @endif */}
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<WunderBar />
|
<WunderBar />
|
||||||
|
@ -94,7 +100,7 @@ const Header = (props: Props) => {
|
||||||
icon={ICONS.UPLOAD}
|
icon={ICONS.UPLOAD}
|
||||||
iconSize={24}
|
iconSize={24}
|
||||||
label={isUpgradeAvailable ? '' : __('Publish')}
|
label={isUpgradeAvailable ? '' : __('Publish')}
|
||||||
onClick={() => navigate('/publish')}
|
navigate="/$/publish"
|
||||||
/>
|
/>
|
||||||
|
|
||||||
{/* @if TARGET='app' */}
|
{/* @if TARGET='app' */}
|
||||||
|
|
|
@ -16,7 +16,7 @@ export default (props: Props) => {
|
||||||
<div className={className || 'help'}>
|
<div className={className || 'help'}>
|
||||||
{numberOfNsfwClaims} {numberOfNsfwClaims > 1 ? __('files') : __('file')}{' '}
|
{numberOfNsfwClaims} {numberOfNsfwClaims > 1 ? __('files') : __('file')}{' '}
|
||||||
{__('hidden due to your')}{' '}
|
{__('hidden due to your')}{' '}
|
||||||
<Button button="link" navigate="/settings" label={__('content viewing preferences')} />.
|
<Button button="link" navigate="/$/settings" label={__('content viewing preferences')} />.
|
||||||
</div>
|
</div>
|
||||||
)
|
)
|
||||||
);
|
);
|
||||||
|
|
|
@ -95,7 +95,7 @@ class InviteNew extends React.PureComponent<Props> {
|
||||||
/>
|
/>
|
||||||
|
|
||||||
<p className="help">
|
<p className="help">
|
||||||
{__('Earn')} <Button button="link" navigate="/rewards" label={__('rewards')} />{' '}
|
{__('Earn')} <Button button="link" navigate="/$/rewards" label={__('rewards')} />{' '}
|
||||||
{__('for inviting your friends.')} {__('Read our')}{' '}
|
{__('for inviting your friends.')} {__('Read our')}{' '}
|
||||||
<Button button="link" label={__('FAQ')} href="https://lbry.com/faq/referrals" />{' '}
|
<Button button="link" label={__('FAQ')} href="https://lbry.com/faq/referrals" />{' '}
|
||||||
{__('to learn more about referrals')}.
|
{__('to learn more about referrals')}.
|
||||||
|
|
|
@ -1,12 +0,0 @@
|
||||||
import { connect } from 'react-redux';
|
|
||||||
import { doNavigate } from 'redux/actions/navigation';
|
|
||||||
import NsfwOverlay from './view';
|
|
||||||
|
|
||||||
const perform = dispatch => ({
|
|
||||||
navigateSettings: () => dispatch(doNavigate('/settings')),
|
|
||||||
});
|
|
||||||
|
|
||||||
export default connect(
|
|
||||||
null,
|
|
||||||
perform
|
|
||||||
)(NsfwOverlay);
|
|
|
@ -1,13 +0,0 @@
|
||||||
import React from 'react';
|
|
||||||
import Button from 'component/button';
|
|
||||||
|
|
||||||
const NsfwOverlay = () => (
|
|
||||||
<div className="card-overlay">
|
|
||||||
<p>
|
|
||||||
{__('This content is Not Safe For Work. To view adult content, please change your')}{' '}
|
|
||||||
<Button button="link" navigate="/settings" label={__('settings')} />.
|
|
||||||
</p>
|
|
||||||
</div>
|
|
||||||
);
|
|
||||||
|
|
||||||
export default NsfwOverlay;
|
|
|
@ -1,33 +1,2 @@
|
||||||
import { connect } from 'react-redux';
|
|
||||||
import {
|
|
||||||
selectBalance,
|
|
||||||
selectPageTitle,
|
|
||||||
selectIsBackDisabled,
|
|
||||||
selectIsForwardDisabled,
|
|
||||||
} from 'lbry-redux';
|
|
||||||
import { doNavigate, doHistoryBack, doHistoryForward } from 'redux/actions/navigation';
|
|
||||||
import { doDownloadUpgrade } from 'redux/actions/app';
|
|
||||||
import { selectIsUpgradeAvailable, selectNavLinks } from 'redux/selectors/app';
|
|
||||||
import { formatCredits } from 'util/format-credits';
|
|
||||||
import Page from './view';
|
import Page from './view';
|
||||||
|
export default Page;
|
||||||
const select = state => ({
|
|
||||||
pageTitle: selectPageTitle(state),
|
|
||||||
navLinks: selectNavLinks(state),
|
|
||||||
isBackDisabled: selectIsBackDisabled(state),
|
|
||||||
isForwardDisabled: selectIsForwardDisabled(state),
|
|
||||||
isUpgradeAvailable: selectIsUpgradeAvailable(state),
|
|
||||||
balance: formatCredits(selectBalance(state) || 0, 2),
|
|
||||||
});
|
|
||||||
|
|
||||||
const perform = dispatch => ({
|
|
||||||
navigate: path => dispatch(doNavigate(path)),
|
|
||||||
back: () => dispatch(doHistoryBack()),
|
|
||||||
forward: () => dispatch(doHistoryForward()),
|
|
||||||
downloadUpgrade: () => dispatch(doDownloadUpgrade()),
|
|
||||||
});
|
|
||||||
|
|
||||||
export default connect(
|
|
||||||
select,
|
|
||||||
perform
|
|
||||||
)(Page);
|
|
||||||
|
|
|
@ -91,11 +91,6 @@ class Page extends React.PureComponent<Props, State> {
|
||||||
'main--extra-padding': extraPadding,
|
'main--extra-padding': extraPadding,
|
||||||
})}
|
})}
|
||||||
>
|
>
|
||||||
{pageTitle && (
|
|
||||||
<div className="page__header">
|
|
||||||
{pageTitle && <h1 className="page__title">{pageTitle}</h1>}
|
|
||||||
</div>
|
|
||||||
)}
|
|
||||||
{!loading && children}
|
{!loading && children}
|
||||||
{showLoader && (
|
{showLoader && (
|
||||||
<div className="page__empty">
|
<div className="page__empty">
|
||||||
|
|
|
@ -1,6 +1,5 @@
|
||||||
import { connect } from 'react-redux';
|
import { connect } from 'react-redux';
|
||||||
import { makeSelectRewardByType, makeSelectIsRewardClaimPending, doClaimRewardType } from 'lbryinc';
|
import { makeSelectRewardByType, makeSelectIsRewardClaimPending, doClaimRewardType } from 'lbryinc';
|
||||||
import { doNavigate } from 'redux/actions/navigation';
|
|
||||||
import RewardLink from './view';
|
import RewardLink from './view';
|
||||||
|
|
||||||
const select = (state, props) => ({
|
const select = (state, props) => ({
|
||||||
|
@ -10,7 +9,6 @@ const select = (state, props) => ({
|
||||||
|
|
||||||
const perform = dispatch => ({
|
const perform = dispatch => ({
|
||||||
claimReward: reward => dispatch(doClaimRewardType(reward.reward_type, { notifyError: true })),
|
claimReward: reward => dispatch(doClaimRewardType(reward.reward_type, { notifyError: true })),
|
||||||
navigate: path => dispatch(doNavigate(path)),
|
|
||||||
});
|
});
|
||||||
|
|
||||||
export default connect(
|
export default connect(
|
||||||
|
|
|
@ -51,7 +51,7 @@ class RewardSummary extends React.Component<Props> {
|
||||||
<div className="card__actions">
|
<div className="card__actions">
|
||||||
<Button
|
<Button
|
||||||
button="primary"
|
button="primary"
|
||||||
navigate="/rewards"
|
navigate="/$/rewards"
|
||||||
label={hasRewards ? __('Claim Rewards') : __('View Rewards')}
|
label={hasRewards ? __('Claim Rewards') : __('View Rewards')}
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
@ -36,7 +36,7 @@ const RewardTile = (props: Props) => {
|
||||||
<Button button="primary" onClick={openRewardCodeModal} label={__('Enter Code')} />
|
<Button button="primary" onClick={openRewardCodeModal} label={__('Enter Code')} />
|
||||||
)}
|
)}
|
||||||
{reward.reward_type === rewards.TYPE_REFERRAL && (
|
{reward.reward_type === rewards.TYPE_REFERRAL && (
|
||||||
<Button button="primary" navigate="/invite" label={__('Go To Invites')} />
|
<Button button="primary" navigate="/$/invite" label={__('Go To Invites')} />
|
||||||
)}
|
)}
|
||||||
{reward.reward_type !== rewards.TYPE_REFERRAL &&
|
{reward.reward_type !== rewards.TYPE_REFERRAL &&
|
||||||
(claimed ? (
|
(claimed ? (
|
||||||
|
|
|
@ -1,14 +1,2 @@
|
||||||
import { connect } from 'react-redux';
|
|
||||||
import { selectCurrentPage, selectCurrentParams, doToast } from 'lbry-redux';
|
|
||||||
import { doOpenModal } from 'redux/actions/app';
|
|
||||||
import Router from './view';
|
import Router from './view';
|
||||||
|
export default Router;
|
||||||
const select = state => ({
|
|
||||||
params: selectCurrentParams(state),
|
|
||||||
currentPage: selectCurrentPage(state),
|
|
||||||
});
|
|
||||||
|
|
||||||
export default connect(
|
|
||||||
select,
|
|
||||||
{ doOpenModal, doToast }
|
|
||||||
)(Router);
|
|
||||||
|
|
|
@ -1,10 +1,10 @@
|
||||||
|
import * as PAGES from 'constants/pages';
|
||||||
import React from 'react';
|
import React from 'react';
|
||||||
|
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 WalletPage from 'page/wallet';
|
||||||
import GetCreditsPage from 'page/getCredits';
|
|
||||||
import SendReceivePage from 'page/sendCredits';
|
|
||||||
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';
|
||||||
|
@ -12,7 +12,6 @@ import RewardsPage from 'page/rewards';
|
||||||
import FileListDownloaded from 'page/fileListDownloaded';
|
import FileListDownloaded from 'page/fileListDownloaded';
|
||||||
import FileListPublished from 'page/fileListPublished';
|
import FileListPublished from 'page/fileListPublished';
|
||||||
import TransactionHistoryPage from 'page/transactionHistory';
|
import TransactionHistoryPage from 'page/transactionHistory';
|
||||||
import ChannelPage from 'page/channel';
|
|
||||||
import AuthPage from 'page/auth';
|
import AuthPage from 'page/auth';
|
||||||
import InvitePage from 'page/invite';
|
import InvitePage from 'page/invite';
|
||||||
import BackupPage from 'page/backup';
|
import BackupPage from 'page/backup';
|
||||||
|
@ -20,41 +19,28 @@ 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';
|
||||||
|
|
||||||
const route = (props, page, routesMap) => {
|
export default function AppRouter(props) {
|
||||||
const component = routesMap[page];
|
return (
|
||||||
if (!component) {
|
<Router>
|
||||||
props.doToast({
|
<DiscoverPage path="/" />
|
||||||
message: __('Invalid page requested'),
|
<ShowPage path="/:claimName/:claimId" />
|
||||||
});
|
<ShowPage path="/:claimName" />
|
||||||
}
|
|
||||||
return component || routesMap.discover;
|
|
||||||
};
|
|
||||||
|
|
||||||
const Router = props => {
|
<AuthPage path={`$/${PAGES.AUTH}`} />
|
||||||
const { currentPage, params } = props;
|
<BackupPage path={`$/${PAGES.BACKUP}`} />
|
||||||
|
<InvitePage path={`$/${PAGES.INVITE}`} />
|
||||||
return route(props, currentPage, {
|
<FileListDownloaded path={`$/${PAGES.DOWNLOADED}`} />
|
||||||
auth: <AuthPage params={params} />,
|
<FileListPublished path={`$/${PAGES.PUBLISHED}`} />
|
||||||
backup: <BackupPage params={params} />,
|
<HelpPage path={`$/${PAGES.HELP}`} />
|
||||||
channel: <ChannelPage params={params} />,
|
<PublishPage path={`$/${PAGES.PUBLISH}`} />
|
||||||
discover: <DiscoverPage params={params} />,
|
<ReportPage path={`$/${PAGES.REPORT}`} />
|
||||||
downloaded: <FileListDownloaded params={params} />,
|
<RewardsPage path={`$/${PAGES.REWARDS}`} />
|
||||||
help: <HelpPage params={params} />,
|
<SearchPage path={`$/${PAGES.SEARCH}`} />
|
||||||
history: <TransactionHistoryPage params={params} />,
|
<SettingsPage path={`$/${PAGES.SETTINGS}`} />
|
||||||
invite: <InvitePage params={params} />,
|
<SubscriptionsPage path={`$/${PAGES.SUBSCRIPTIONS}`} />
|
||||||
publish: <PublishPage params={params} />,
|
<TransactionHistoryPage path={`$/${PAGES.HISTORY}`} />
|
||||||
published: <FileListPublished params={params} />,
|
<UserHistoryPage path={`$/${PAGES.USER_HISTORY}`} />
|
||||||
getcredits: <GetCreditsPage params={params} />,
|
<WalletPage path={`$/${PAGES.WALLET}`} />
|
||||||
report: <ReportPage params={params} />,
|
</Router>
|
||||||
rewards: <RewardsPage params={params} />,
|
);
|
||||||
send: <SendReceivePage params={params} />,
|
}
|
||||||
settings: <SettingsPage params={params} />,
|
|
||||||
show: <ShowPage {...params} />,
|
|
||||||
wallet: <WalletPage params={params} />,
|
|
||||||
subscriptions: <SubscriptionsPage params={params} />,
|
|
||||||
search: <SearchPage {...params} />,
|
|
||||||
user_history: <UserHistoryPage {...params} />,
|
|
||||||
});
|
|
||||||
};
|
|
||||||
|
|
||||||
export default Router;
|
|
||||||
|
|
|
@ -8,7 +8,7 @@ import Button from 'component/button';
|
||||||
|
|
||||||
const ExpandableOptions = posed.div({
|
const ExpandableOptions = posed.div({
|
||||||
hide: { height: 0, opacity: 0 },
|
hide: { height: 0, opacity: 0 },
|
||||||
show: { height: 280, opacity: 1 },
|
show: { height: 300, opacity: 1 },
|
||||||
});
|
});
|
||||||
|
|
||||||
type Props = {
|
type Props = {
|
||||||
|
@ -34,11 +34,11 @@ const SearchOptions = (props: Props) => {
|
||||||
const resultCount = options[SEARCH_OPTIONS.RESULT_COUNT];
|
const resultCount = options[SEARCH_OPTIONS.RESULT_COUNT];
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="card card--section search__options-wrapper">
|
<div className="search__options-wrapper">
|
||||||
<div className="card--space-between">
|
<div className="card--space-between">
|
||||||
<Button
|
<Button
|
||||||
button="alt"
|
button="alt"
|
||||||
label={__('ADVANCED SEARCH')}
|
label={__('FILTER')}
|
||||||
iconRight={expanded ? ICONS.UP : ICONS.DOWN}
|
iconRight={expanded ? ICONS.UP : ICONS.DOWN}
|
||||||
onClick={toggleSearchExpanded}
|
onClick={toggleSearchExpanded}
|
||||||
/>
|
/>
|
||||||
|
|
|
@ -1,10 +1,8 @@
|
||||||
import { connect } from 'react-redux';
|
import { connect } from 'react-redux';
|
||||||
import { selectNavLinks } from 'redux/selectors/app';
|
|
||||||
import { selectUnreadAmount } from 'redux/selectors/subscriptions';
|
import { selectUnreadAmount } from 'redux/selectors/subscriptions';
|
||||||
import SideBar from './view';
|
import SideBar from './view';
|
||||||
|
|
||||||
const select = state => ({
|
const select = state => ({
|
||||||
navLinks: selectNavLinks(state),
|
|
||||||
unreadSubscriptionTotal: selectUnreadAmount(state),
|
unreadSubscriptionTotal: selectUnreadAmount(state),
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
|
@ -1,4 +1,6 @@
|
||||||
// @flow
|
// @flow
|
||||||
|
|||||||
|
import * as PAGES from 'constants/pages';
|
||||||
|
import * as ICONS from 'constants/icons';
|
||||||
import * as React from 'react';
|
import * as React from 'react';
|
||||||
import Button from 'component/button';
|
import Button from 'component/button';
|
||||||
import classnames from 'classnames';
|
import classnames from 'classnames';
|
||||||
|
@ -14,86 +16,96 @@ type SideBarLink = {
|
||||||
};
|
};
|
||||||
|
|
||||||
type Props = {
|
type Props = {
|
||||||
navLinks: {
|
|
||||||
primary: Array<SideBarLink>,
|
|
||||||
secondary: Array<SideBarLink>,
|
|
||||||
},
|
|
||||||
unreadSubscriptionTotal: number,
|
unreadSubscriptionTotal: number,
|
||||||
};
|
};
|
||||||
|
|
||||||
class SideBar extends React.PureComponent<Props> {
|
class SideBar extends React.PureComponent<Props> {
|
||||||
renderNavLink(navLink: SideBarLink) {
|
render() {
|
||||||
const { label, path, active, subLinks = [], icon, guide } = navLink;
|
const { unreadSubscriptionTotal } = this.props;
|
||||||
|
const buildLink = (path, label, icon) => ({
|
||||||
|
navigate: path ? `$/${path}` : '/',
|
||||||
|
label,
|
||||||
|
icon,
|
||||||
|
});
|
||||||
|
|
||||||
const inner = (
|
const renderLink = (linkProps, index) => (
|
||||||
<li
|
<li key={index}>
|
||||||
className={classnames('navigation__link', {
|
<Button
|
||||||
'navigation__link--active': active,
|
{...linkProps}
|
||||||
'navigation__link--guide': guide,
|
className="navigation__link"
|
||||||
})}
|
activeClass="navigation__link--active"
|
||||||
key={label}
|
/>
|
||||||
>
|
|
||||||
<Button icon={icon} label={label} navigate={path} />
|
|
||||||
|
|
||||||
{
|
|
||||||
// The sublinks should be animated on open close
|
|
||||||
// Removing it because the current implementation with CSSTransitionGroup
|
|
||||||
// was really slow and looked pretty bad. Possible fix is upgrading to v2
|
|
||||||
// Not sure if that has better performance
|
|
||||||
}
|
|
||||||
{!!subLinks.length && active && (
|
|
||||||
<ul key="0" className="navigation__link-items">
|
|
||||||
{subLinks.map(({ active: subLinkActive, label: subLabel, path: subPath }) => (
|
|
||||||
<li
|
|
||||||
className={classnames('navigation__link-item', {
|
|
||||||
'navigation__link-item--active': subLinkActive,
|
|
||||||
})}
|
|
||||||
key={subPath}
|
|
||||||
>
|
|
||||||
{subPath ? <Button label={subLabel} navigate={subPath} /> : <span>{subLabel}</span>}
|
|
||||||
</li>
|
|
||||||
))}
|
|
||||||
</ul>
|
|
||||||
)}
|
|
||||||
</li>
|
</li>
|
||||||
);
|
);
|
||||||
|
|
||||||
return guide ? (
|
|
||||||
<Tooltip key={guide} alwaysVisible direction="right" body={guide}>
|
|
||||||
{inner}
|
|
||||||
</Tooltip>
|
|
||||||
) : (
|
|
||||||
inner
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
render() {
|
|
||||||
const { navLinks, unreadSubscriptionTotal } = this.props;
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<nav className="navigation">
|
<nav className="navigation">
|
||||||
<div className="navigation__links">
|
<ul className="navigation__links">
|
||||||
{navLinks.primary.map(({ label, path, active, icon }) => (
|
{[
|
||||||
<Button
|
{
|
||||||
icon={icon}
|
...buildLink(null, __('Home'), ICONS.HOME),
|
||||||
className={classnames('navigation__link', {
|
},
|
||||||
'navigation__link--active': active,
|
{
|
||||||
})}
|
...buildLink(
|
||||||
key={path}
|
PAGES.SUBSCRIPTIONS,
|
||||||
label={
|
`${__('Subscriptions')} ${
|
||||||
path === '/subscriptions' && unreadSubscriptionTotal
|
unreadSubscriptionTotal > 0 ? '(' + unreadSubscriptionTotal + ')' : ''
|
||||||
? `${label} (${unreadSubscriptionTotal})`
|
}`,
|
||||||
: label
|
ICONS.SUBSCRIPTION
|
||||||
}
|
),
|
||||||
navigate={path}
|
},
|
||||||
/>
|
].map(renderLink)}
|
||||||
))}
|
</ul>
|
||||||
|
|
||||||
|
<div className="navigation__link navigation__link--title">My LBRY</div>
|
||||||
|
|
||||||
|
<div className="navigation__links">
|
||||||
<ul>
|
<ul>
|
||||||
<li className="navigation__link navigation__link--title">Account</li>
|
{[
|
||||||
{navLinks.secondary.map(this.renderNavLink)}
|
{
|
||||||
|
...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>
|
</ul>
|
||||||
</div>
|
</div>
|
||||||
|
<div className="navigation__link navigation__link--title">Wallet</div>
|
||||||
|
|
||||||
|
<ul className="navigation__links">
|
||||||
|
{[
|
||||||
|
{
|
||||||
|
...buildLink(PAGES.WALLET, 'Overview', ICONS.WALLET),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
...buildLink(PAGES.HISTORY, 'Transactions', ICONS.TRANSACTIONS),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
...buildLink(PAGES.BACKUP, 'Backup', ICONS.BACKUP),
|
||||||
|
},
|
||||||
|
].map(renderLink)}
|
||||||
|
</ul>
|
||||||
|
|
||||||
|
<ul className="navigation__links navigation__links--bottom">
|
||||||
|
{[
|
||||||
|
{
|
||||||
|
...buildLink(PAGES.SETTINGS, 'Settings', ICONS.SETTINGS),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
...buildLink(PAGES.HELP, 'Help', ICONS.HELP),
|
||||||
|
},
|
||||||
|
].map(renderLink)}
|
||||||
|
</ul>
|
||||||
</nav>
|
</nav>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,6 +1,5 @@
|
||||||
import { connect } from 'react-redux';
|
import { connect } from 'react-redux';
|
||||||
import { selectClaimedRewardsByTransactionId } from 'lbryinc';
|
import { selectClaimedRewardsByTransactionId } from 'lbryinc';
|
||||||
import { doNavigate } from 'redux/actions/navigation';
|
|
||||||
import { doOpenModal } from 'redux/actions/app';
|
import { doOpenModal } from 'redux/actions/app';
|
||||||
import {
|
import {
|
||||||
selectAllMyClaimsByOutpoint,
|
selectAllMyClaimsByOutpoint,
|
||||||
|
@ -16,7 +15,6 @@ const select = state => ({
|
||||||
});
|
});
|
||||||
|
|
||||||
const perform = dispatch => ({
|
const perform = dispatch => ({
|
||||||
navigate: (path, params) => dispatch(doNavigate(path, params)),
|
|
||||||
openModal: (modal, props) => dispatch(doOpenModal(modal, props)),
|
openModal: (modal, props) => dispatch(doOpenModal(modal, props)),
|
||||||
setTransactionFilter: filterSetting => dispatch(doSetTransactionListFilter(filterSetting)),
|
setTransactionFilter: filterSetting => dispatch(doSetTransactionListFilter(filterSetting)),
|
||||||
});
|
});
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
// @flow
|
// @flow
|
||||||
import type { Transaction } from 'types/transaction';
|
import type { Transaction } from 'types/transaction';
|
||||||
|
import * as TXN_TYPES from 'constants/transaction_types';
|
||||||
import * as ICONS from 'constants/icons';
|
import * as ICONS from 'constants/icons';
|
||||||
import React from 'react';
|
import React from 'react';
|
||||||
import ButtonTransaction from 'component/common/transaction-link';
|
import ButtonTransaction from 'component/common/transaction-link';
|
||||||
|
@ -7,7 +8,7 @@ import CreditAmount from 'component/common/credit-amount';
|
||||||
import DateTime from 'component/dateTime';
|
import DateTime from 'component/dateTime';
|
||||||
import Button from 'component/button';
|
import Button from 'component/button';
|
||||||
import { buildURI } from 'lbry-redux';
|
import { buildURI } from 'lbry-redux';
|
||||||
import * as txnTypes from 'constants/transaction_types';
|
import { formatLbryUriForWeb } from 'util/uri';
|
||||||
|
|
||||||
type Props = {
|
type Props = {
|
||||||
transaction: Transaction,
|
transaction: Transaction,
|
||||||
|
@ -26,7 +27,7 @@ class TransactionListItem extends React.PureComponent<Props> {
|
||||||
}
|
}
|
||||||
|
|
||||||
getLink(type: string) {
|
getLink(type: string) {
|
||||||
if (type === txnTypes.TIP) {
|
if (type === TXN_TYPES.TIP) {
|
||||||
return <Button icon={ICONS.UNLOCK} onClick={this.abandonClaim} title={__('Unlock Tip')} />;
|
return <Button icon={ICONS.UNLOCK} onClick={this.abandonClaim} title={__('Unlock Tip')} />;
|
||||||
}
|
}
|
||||||
return <Button icon={ICONS.DELETE} onClick={this.abandonClaim} title={__('Abandon Claim')} />;
|
return <Button icon={ICONS.DELETE} onClick={this.abandonClaim} title={__('Abandon Claim')} />;
|
||||||
|
@ -68,12 +69,7 @@ class TransactionListItem extends React.PureComponent<Props> {
|
||||||
<td className="table__item--actionable">
|
<td className="table__item--actionable">
|
||||||
{reward && <span>{reward.reward_title}</span>}
|
{reward && <span>{reward.reward_title}</span>}
|
||||||
{name && claimId && (
|
{name && claimId && (
|
||||||
<Button
|
<Button constrict button="link" navigate={buildURI({ claimName: name, claimId })}>
|
||||||
constrict
|
|
||||||
button="link"
|
|
||||||
navigate="/show"
|
|
||||||
navigateParams={{ uri: buildURI({ claimName: name, claimId }) }}
|
|
||||||
>
|
|
||||||
{name}
|
{name}
|
||||||
</Button>
|
</Button>
|
||||||
)}
|
)}
|
||||||
|
|
|
@ -105,12 +105,10 @@ class TransactionList extends React.PureComponent<Props> {
|
||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
</header>
|
</header>
|
||||||
{!transactionList.length && (
|
{!transactionList.length && <p>{emptyMessage || __('No transactions to list.')}</p>}
|
||||||
<p className="card__content">{emptyMessage || __('No transactions to list.')}</p>
|
|
||||||
)}
|
|
||||||
|
|
||||||
{!!transactionList.length && (
|
{!!transactionList.length && (
|
||||||
<div className="card__content">
|
<React.Fragment>
|
||||||
<table className="table table--transactions">
|
<table className="table table--transactions">
|
||||||
<thead>
|
<thead>
|
||||||
<tr>
|
<tr>
|
||||||
|
@ -133,7 +131,7 @@ class TransactionList extends React.PureComponent<Props> {
|
||||||
))}
|
))}
|
||||||
</tbody>
|
</tbody>
|
||||||
</table>
|
</table>
|
||||||
</div>
|
</React.Fragment>
|
||||||
)}
|
)}
|
||||||
</React.Fragment>
|
</React.Fragment>
|
||||||
);
|
);
|
||||||
|
|
|
@ -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="/$/history" label={__('transactions page')} />.
|
||||||
</p>
|
</p>
|
||||||
</header>
|
</header>
|
||||||
|
|
||||||
|
@ -53,14 +53,14 @@ class TransactionListRecent extends React.PureComponent<Props> {
|
||||||
transactions={transactions}
|
transactions={transactions}
|
||||||
emptyMessage={__("Looks like you don't have any recent transactions.")}
|
emptyMessage={__("Looks like you don't have any recent transactions.")}
|
||||||
/>
|
/>
|
||||||
<div className="card__actions">
|
</div>
|
||||||
<Button
|
<div className="card__actions">
|
||||||
button="primary"
|
<Button
|
||||||
navigate="/history"
|
button="primary"
|
||||||
label={__('Full History')}
|
navigate="/$/history"
|
||||||
icon={icons.HISTORY}
|
label={__('Full History')}
|
||||||
/>
|
icon={icons.HISTORY}
|
||||||
</div>
|
/>
|
||||||
</div>
|
</div>
|
||||||
</Fragment>
|
</Fragment>
|
||||||
)}
|
)}
|
||||||
|
|
|
@ -57,12 +57,7 @@ class UriIndicator extends React.PureComponent<Props> {
|
||||||
}
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Button
|
<Button noPadding className="button--uri-indicator" navigate={channelLink}>
|
||||||
noPadding
|
|
||||||
className="button--uri-indicator"
|
|
||||||
navigate="/show"
|
|
||||||
navigateParams={{ uri: channelLink, page: 1 }}
|
|
||||||
>
|
|
||||||
{inner}
|
{inner}
|
||||||
</Button>
|
</Button>
|
||||||
);
|
);
|
||||||
|
|
|
@ -5,7 +5,6 @@ import {
|
||||||
doUserCheckEmailVerified,
|
doUserCheckEmailVerified,
|
||||||
selectUser,
|
selectUser,
|
||||||
} from 'lbryinc';
|
} from 'lbryinc';
|
||||||
import { doNavigate } from 'redux/actions/navigation';
|
|
||||||
import UserEmailVerify from './view';
|
import UserEmailVerify from './view';
|
||||||
|
|
||||||
const select = state => ({
|
const select = state => ({
|
||||||
|
@ -16,7 +15,6 @@ const select = state => ({
|
||||||
const perform = dispatch => ({
|
const perform = dispatch => ({
|
||||||
resendVerificationEmail: email => dispatch(doUserResendVerificationEmail(email)),
|
resendVerificationEmail: email => dispatch(doUserResendVerificationEmail(email)),
|
||||||
checkEmailVerified: () => dispatch(doUserCheckEmailVerified()),
|
checkEmailVerified: () => dispatch(doUserCheckEmailVerified()),
|
||||||
navigate: path => dispatch(doNavigate(path)),
|
|
||||||
});
|
});
|
||||||
|
|
||||||
export default connect(
|
export default connect(
|
||||||
|
|
|
@ -1,22 +1,22 @@
|
||||||
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 { doNavigate } from 'redux/actions/navigation';
|
|
||||||
import { selectCurrentParams, makeSelectCurrentParam } from 'lbry-redux';
|
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';
|
||||||
|
|
||||||
const select = state => {
|
const select = (state, props) => {
|
||||||
const paramPage = Number(makeSelectCurrentParam('page')(state) || 0);
|
const { search } = props.location;
|
||||||
|
const urlParams = new URLSearchParams(search);
|
||||||
|
const page = Number(urlParams.get('page')) || 0;
|
||||||
|
|
||||||
return {
|
return {
|
||||||
|
page,
|
||||||
pageCount: selectHistoryPageCount(state),
|
pageCount: selectHistoryPageCount(state),
|
||||||
page: paramPage,
|
history: makeSelectHistoryForPage(page)(state),
|
||||||
params: selectCurrentParams(state),
|
|
||||||
history: makeSelectHistoryForPage(paramPage)(state),
|
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
const perform = dispatch => ({
|
const perform = dispatch => ({
|
||||||
navigate: (path, params) => dispatch(doNavigate(path, params)),
|
|
||||||
clearHistoryUri: uri => dispatch(doClearContentHistoryUri(uri)),
|
clearHistoryUri: uri => dispatch(doClearContentHistoryUri(uri)),
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
|
@ -4,6 +4,7 @@ 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 UserHistoryItem from 'component/userHistoryItem';
|
||||||
|
import { navigate } from '@reach/router';
|
||||||
|
|
||||||
type HistoryItem = {
|
type HistoryItem = {
|
||||||
uri: string,
|
uri: string,
|
||||||
|
@ -14,7 +15,6 @@ type Props = {
|
||||||
history: Array<HistoryItem>,
|
history: Array<HistoryItem>,
|
||||||
page: number,
|
page: number,
|
||||||
pageCount: number,
|
pageCount: number,
|
||||||
navigate: (string, {}) => void,
|
|
||||||
clearHistoryUri: string => void,
|
clearHistoryUri: string => void,
|
||||||
params: { page: number },
|
params: { page: number },
|
||||||
};
|
};
|
||||||
|
@ -52,9 +52,8 @@ class UserHistoryPage extends React.PureComponent<Props, State> {
|
||||||
}
|
}
|
||||||
|
|
||||||
changePage(pageNumber: number) {
|
changePage(pageNumber: number) {
|
||||||
const { params } = this.props;
|
console.log('new', pageNumber);
|
||||||
const newParams = { ...params, page: pageNumber };
|
navigate(`/$/user_history?page=${pageNumber}`);
|
||||||
this.props.navigate('/user_history', newParams);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
paginate(e: SyntheticKeyboardEvent<*>) {
|
paginate(e: SyntheticKeyboardEvent<*>) {
|
||||||
|
@ -94,7 +93,8 @@ 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;
|
||||||
|
@ -148,6 +148,7 @@ class UserHistoryPage extends React.PureComponent<Props, State> {
|
||||||
onPageChange={e => this.changePage(e.selected)}
|
onPageChange={e => this.changePage(e.selected)}
|
||||||
forcePage={page}
|
forcePage={page}
|
||||||
initialPage={page}
|
initialPage={page}
|
||||||
|
disableInitialCallback
|
||||||
containerClassName="pagination"
|
containerClassName="pagination"
|
||||||
/>
|
/>
|
||||||
</fieldset-section>
|
</fieldset-section>
|
||||||
|
@ -175,7 +176,7 @@ class UserHistoryPage extends React.PureComponent<Props, State> {
|
||||||
|
|
||||||
<div className="card__content">
|
<div className="card__content">
|
||||||
<div className="card__actions card__actions--center">
|
<div className="card__actions card__actions--center">
|
||||||
<Button button="primary" navigate="/discover" label={__('Explore new content')} />
|
<Button button="primary" navigate="/" label={__('Explore new content')} />
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</section>
|
</section>
|
||||||
|
|
|
@ -51,8 +51,7 @@ class UserHistoryItem extends React.PureComponent<Props> {
|
||||||
constrict
|
constrict
|
||||||
button="link"
|
button="link"
|
||||||
label={name ? `lbry://${name}` : `lbry://...`}
|
label={name ? `lbry://${name}` : `lbry://...`}
|
||||||
navigate="/show"
|
navigate={uri}
|
||||||
navigateParams={{ uri }}
|
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
|
|
|
@ -1,7 +1,6 @@
|
||||||
import * as MODALS from 'constants/modal_types';
|
import * as MODALS from 'constants/modal_types';
|
||||||
import { connect } from 'react-redux';
|
import { connect } from 'react-redux';
|
||||||
import { doOpenModal } from 'redux/actions/app';
|
import { doOpenModal } from 'redux/actions/app';
|
||||||
import { doNavigate } from 'redux/actions/navigation';
|
|
||||||
import {
|
import {
|
||||||
doUserIdentityVerify,
|
doUserIdentityVerify,
|
||||||
rewards,
|
rewards,
|
||||||
|
@ -22,7 +21,6 @@ const select = state => {
|
||||||
};
|
};
|
||||||
|
|
||||||
const perform = dispatch => ({
|
const perform = dispatch => ({
|
||||||
navigate: uri => dispatch(doNavigate(uri)),
|
|
||||||
verifyUserIdentity: token => dispatch(doUserIdentityVerify(token)),
|
verifyUserIdentity: token => dispatch(doUserIdentityVerify(token)),
|
||||||
verifyPhone: () => dispatch(doOpenModal(MODALS.PHONE_COLLECTION)),
|
verifyPhone: () => dispatch(doOpenModal(MODALS.PHONE_COLLECTION)),
|
||||||
});
|
});
|
||||||
|
|
|
@ -8,7 +8,6 @@ import { Lbryio } from 'lbryinc';
|
||||||
type Props = {
|
type Props = {
|
||||||
errorMessage: ?string,
|
errorMessage: ?string,
|
||||||
isPending: boolean,
|
isPending: boolean,
|
||||||
navigate: string => void,
|
|
||||||
verifyUserIdentity: string => void,
|
verifyUserIdentity: string => void,
|
||||||
verifyPhone: () => void,
|
verifyPhone: () => void,
|
||||||
};
|
};
|
||||||
|
@ -25,7 +24,7 @@ class UserVerify extends React.PureComponent<Props> {
|
||||||
}
|
}
|
||||||
|
|
||||||
render() {
|
render() {
|
||||||
const { errorMessage, isPending, navigate, verifyPhone } = this.props;
|
const { errorMessage, isPending, verifyPhone } = this.props;
|
||||||
return (
|
return (
|
||||||
<React.Fragment>
|
<React.Fragment>
|
||||||
<section className="card card--section">
|
<section className="card card--section">
|
||||||
|
@ -137,11 +136,7 @@ class UserVerify extends React.PureComponent<Props> {
|
||||||
|
|
||||||
<div className="card__content">
|
<div className="card__content">
|
||||||
<div className="card__actions">
|
<div className="card__actions">
|
||||||
<Button
|
<Button navigate="/" button="primary" label={__('Skip Rewards')} />
|
||||||
onClick={() => navigate('/discover')}
|
|
||||||
button="primary"
|
|
||||||
label={__('Skip Rewards')}
|
|
||||||
/>
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</section>
|
</section>
|
||||||
|
|
|
@ -2,7 +2,9 @@
|
||||||
import * as React from 'react';
|
import * as React from 'react';
|
||||||
import { stopContextMenu } from 'util/context-menu';
|
import { stopContextMenu } from 'util/context-menu';
|
||||||
import Button from 'component/button';
|
import Button from 'component/button';
|
||||||
|
// @if TARGET='app'
|
||||||
import { shell } from 'electron';
|
import { shell } from 'electron';
|
||||||
|
// @endif
|
||||||
|
|
||||||
type Props = {
|
type Props = {
|
||||||
source: string,
|
source: string,
|
||||||
|
@ -22,7 +24,12 @@ class PdfViewer extends React.PureComponent<Props> {
|
||||||
openFile() {
|
openFile() {
|
||||||
const { source } = this.props;
|
const { source } = this.props;
|
||||||
const path = `file://${source}`;
|
const path = `file://${source}`;
|
||||||
|
// @if TARGET='app'
|
||||||
shell.openExternal(path);
|
shell.openExternal(path);
|
||||||
|
// @endif
|
||||||
|
// @if TARGET='web'
|
||||||
|
console.error('provide stub for shell.openExternal');
|
||||||
|
// @endif
|
||||||
}
|
}
|
||||||
|
|
||||||
render() {
|
render() {
|
||||||
|
|
|
@ -12,7 +12,7 @@ const WalletBalance = (props: Props) => {
|
||||||
return (
|
return (
|
||||||
<section
|
<section
|
||||||
className="card card--section card--wallet-balance"
|
className="card card--section card--wallet-balance"
|
||||||
style={{ backgroundImage: `url(${BalanceBackground})` }}
|
style={{ backgroundImage: `url(/${BalanceBackground})` }}
|
||||||
>
|
>
|
||||||
<header className="card__header">
|
<header className="card__header">
|
||||||
<h2 className="card__title">{__('Balance')}</h2>
|
<h2 className="card__title">{__('Balance')}</h2>
|
||||||
|
|
|
@ -1,44 +1,38 @@
|
||||||
import { connect } from 'react-redux';
|
import { connect } from 'react-redux';
|
||||||
import {
|
import {
|
||||||
selectSearchState as selectSearch,
|
|
||||||
selectWunderBarAddress,
|
|
||||||
selectSearchSuggestions,
|
|
||||||
doUpdateSearchQuery,
|
|
||||||
doFocusSearchInput,
|
doFocusSearchInput,
|
||||||
doBlurSearchInput,
|
doBlurSearchInput,
|
||||||
|
doUpdateSearchQuery,
|
||||||
doSearch,
|
doSearch,
|
||||||
doToast,
|
selectSearchValue,
|
||||||
|
selectSearchSuggestions,
|
||||||
|
selectSearchBarFocused,
|
||||||
|
parseURI,
|
||||||
} from 'lbry-redux';
|
} from 'lbry-redux';
|
||||||
import analytics from 'analytics';
|
import analytics from 'analytics';
|
||||||
import { doNavigate } from 'redux/actions/navigation';
|
|
||||||
import Wunderbar from './view';
|
import Wunderbar from './view';
|
||||||
|
import { navigate } from '@reach/router';
|
||||||
|
import { formatLbryUriForWeb } from 'util/uri';
|
||||||
|
|
||||||
const select = state => {
|
const select = state => ({
|
||||||
const { isActive, searchQuery, ...searchState } = selectSearch(state);
|
suggestions: selectSearchSuggestions(state),
|
||||||
const address = selectWunderBarAddress(state);
|
searchQuery: selectSearchValue(state),
|
||||||
|
isFocused: selectSearchBarFocused(state),
|
||||||
// if we are on the file/channel page
|
});
|
||||||
// use the address in the history stack
|
|
||||||
const wunderbarValue = isActive ? searchQuery : searchQuery || address;
|
|
||||||
|
|
||||||
return {
|
|
||||||
...searchState,
|
|
||||||
wunderbarValue,
|
|
||||||
suggestions: selectSearchSuggestions(state),
|
|
||||||
};
|
|
||||||
};
|
|
||||||
|
|
||||||
const perform = dispatch => ({
|
const perform = dispatch => ({
|
||||||
onSearch: query => {
|
onSearch: query => {
|
||||||
dispatch(doSearch(query));
|
navigate(`/$/search?q=${query}`);
|
||||||
dispatch(doNavigate(`/search`, { query }));
|
|
||||||
analytics.apiLogSearch();
|
analytics.apiLogSearch();
|
||||||
},
|
},
|
||||||
onSubmit: (uri, extraParams) => dispatch(doNavigate('/show', { uri, ...extraParams })),
|
onSubmit: uri => {
|
||||||
|
const path = formatLbryUriForWeb(uri);
|
||||||
|
navigate(path);
|
||||||
|
dispatch(doUpdateSearchQuery(''));
|
||||||
|
},
|
||||||
updateSearchQuery: query => dispatch(doUpdateSearchQuery(query)),
|
updateSearchQuery: query => dispatch(doUpdateSearchQuery(query)),
|
||||||
doFocus: () => dispatch(doFocusSearchInput()),
|
doFocus: () => dispatch(doFocusSearchInput()),
|
||||||
doBlur: () => dispatch(doBlurSearchInput()),
|
doBlur: () => dispatch(doBlurSearchInput()),
|
||||||
doShowSnackBar: props => dispatch(doToast(props)),
|
|
||||||
});
|
});
|
||||||
|
|
||||||
export default connect(
|
export default connect(
|
||||||
|
|
|
@ -1,19 +1,22 @@
|
||||||
// @flow
|
// @flow
|
||||||
|
import * as PAGES from 'constants/pages';
|
||||||
import * as ICONS from 'constants/icons';
|
import * as ICONS from 'constants/icons';
|
||||||
import React from 'react';
|
import React from 'react';
|
||||||
import classnames from 'classnames';
|
import classnames from 'classnames';
|
||||||
import { normalizeURI, SEARCH_TYPES, isURIValid } from 'lbry-redux';
|
import { normalizeURI, SEARCH_TYPES, isURIValid, buildURI } from 'lbry-redux';
|
||||||
import Icon from 'component/common/icon';
|
import Icon from 'component/common/icon';
|
||||||
import { parseQueryParams } from 'util/query-params';
|
import { parseQueryParams } from 'util/query-params';
|
||||||
import Autocomplete from './internal/autocomplete';
|
import Autocomplete from './internal/autocomplete';
|
||||||
|
import { Location, navigate } from '@reach/router';
|
||||||
|
|
||||||
const L_KEY_CODE = 76;
|
const L_KEY_CODE = 76;
|
||||||
const ESC_KEY_CODE = 27;
|
const ESC_KEY_CODE = 27;
|
||||||
|
|
||||||
type Props = {
|
type Props = {
|
||||||
|
searchQuery: ?string,
|
||||||
updateSearchQuery: string => void,
|
updateSearchQuery: string => void,
|
||||||
onSearch: string => void,
|
onSearch: string => void,
|
||||||
onSubmit: (string, {}) => void,
|
onSubmit: string => void,
|
||||||
wunderbarValue: ?string,
|
wunderbarValue: ?string,
|
||||||
suggestions: Array<string>,
|
suggestions: Array<string>,
|
||||||
doFocus: () => void,
|
doFocus: () => void,
|
||||||
|
@ -22,10 +25,18 @@ type Props = {
|
||||||
doShowSnackBar: ({}) => void,
|
doShowSnackBar: ({}) => void,
|
||||||
};
|
};
|
||||||
|
|
||||||
class WunderBar extends React.PureComponent<Props> {
|
type State = {
|
||||||
|
query: ?string,
|
||||||
|
};
|
||||||
|
|
||||||
|
class WunderBar extends React.PureComponent<Props, State> {
|
||||||
constructor() {
|
constructor() {
|
||||||
super();
|
super();
|
||||||
|
|
||||||
|
this.state = {
|
||||||
|
query: null,
|
||||||
|
};
|
||||||
|
|
||||||
(this: any).handleSubmit = this.handleSubmit.bind(this);
|
(this: any).handleSubmit = this.handleSubmit.bind(this);
|
||||||
(this: any).handleChange = this.handleChange.bind(this);
|
(this: any).handleChange = this.handleChange.bind(this);
|
||||||
(this: any).handleKeyDown = this.handleKeyDown.bind(this);
|
(this: any).handleKeyDown = this.handleKeyDown.bind(this);
|
||||||
|
@ -61,6 +72,7 @@ class WunderBar extends React.PureComponent<Props> {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// @if TARGET='app'
|
||||||
const shouldFocus =
|
const shouldFocus =
|
||||||
process.platform === 'darwin'
|
process.platform === 'darwin'
|
||||||
? keyCode === L_KEY_CODE && metaKey
|
? keyCode === L_KEY_CODE && metaKey
|
||||||
|
@ -70,30 +82,20 @@ class WunderBar extends React.PureComponent<Props> {
|
||||||
this.input.focus();
|
this.input.focus();
|
||||||
doFocus();
|
doFocus();
|
||||||
}
|
}
|
||||||
|
// @endif
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
handleChange(e: SyntheticInputEvent<*>) {
|
handleChange(e: SyntheticInputEvent<*>) {
|
||||||
const { updateSearchQuery } = this.props;
|
|
||||||
const { value } = e.target;
|
const { value } = e.target;
|
||||||
|
const { updateSearchQuery } = this.props;
|
||||||
updateSearchQuery(value);
|
updateSearchQuery(value);
|
||||||
}
|
}
|
||||||
|
|
||||||
handleSubmit(value: string, suggestion?: { value: string, type: string }) {
|
handleSubmit(value: string, suggestion?: { value: string, type: string }) {
|
||||||
const { onSubmit, onSearch, doShowSnackBar } = this.props;
|
const { onSubmit, onSearch, doShowSnackBar } = this.props;
|
||||||
|
|
||||||
const query = value.trim();
|
const query = value.trim();
|
||||||
const getParams = () => {
|
|
||||||
const parts = query.split('?');
|
|
||||||
|
|
||||||
let extraParams = {};
|
|
||||||
if (parts.length > 0) {
|
|
||||||
extraParams = parseQueryParams(parts.join(''));
|
|
||||||
}
|
|
||||||
|
|
||||||
return extraParams;
|
|
||||||
};
|
|
||||||
|
|
||||||
const showSnackError = () => {
|
const showSnackError = () => {
|
||||||
doShowSnackBar({
|
doShowSnackBar({
|
||||||
message: __('Invalid LBRY URL entered. Only A-Z, a-z, 0-9, and "-" allowed.'),
|
message: __('Invalid LBRY URL entered. Only A-Z, a-z, 0-9, and "-" allowed.'),
|
||||||
|
@ -105,23 +107,20 @@ class WunderBar extends React.PureComponent<Props> {
|
||||||
if (suggestion.type === 'search') {
|
if (suggestion.type === 'search') {
|
||||||
onSearch(query);
|
onSearch(query);
|
||||||
} else if (isURIValid(query)) {
|
} else if (isURIValid(query)) {
|
||||||
const params = getParams();
|
|
||||||
const uri = normalizeURI(query);
|
const uri = normalizeURI(query);
|
||||||
onSubmit(uri, params);
|
onSubmit(uri);
|
||||||
} else {
|
} else {
|
||||||
showSnackError();
|
showSnackError();
|
||||||
}
|
}
|
||||||
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Currently no suggestion is highlighted. The user may have started
|
// Currently no suggestion is highlighted. The user may have started
|
||||||
// typing, then lost focus and came back later on the same page
|
// typing, then lost focus and came back later on the same page
|
||||||
try {
|
try {
|
||||||
if (isURIValid(query)) {
|
if (isURIValid(query)) {
|
||||||
const uri = normalizeURI(query);
|
const uri = normalizeURI(query);
|
||||||
const params = getParams();
|
onSubmit(uri);
|
||||||
onSubmit(uri, params);
|
|
||||||
} else {
|
} else {
|
||||||
showSnackError();
|
showSnackError();
|
||||||
}
|
}
|
||||||
|
@ -133,7 +132,7 @@ class WunderBar extends React.PureComponent<Props> {
|
||||||
input: ?HTMLInputElement;
|
input: ?HTMLInputElement;
|
||||||
|
|
||||||
render() {
|
render() {
|
||||||
const { wunderbarValue, suggestions, doFocus, doBlur } = this.props;
|
const { suggestions, doFocus, doBlur, searchQuery } = this.props;
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="wunderbar">
|
<div className="wunderbar">
|
||||||
|
@ -141,7 +140,7 @@ class WunderBar extends React.PureComponent<Props> {
|
||||||
<Autocomplete
|
<Autocomplete
|
||||||
autoHighlight
|
autoHighlight
|
||||||
wrapperStyle={{ flex: 1, position: 'relative' }}
|
wrapperStyle={{ flex: 1, position: 'relative' }}
|
||||||
value={wunderbarValue || ''}
|
value={searchQuery}
|
||||||
items={suggestions}
|
items={suggestions}
|
||||||
getItemValue={item => item.value}
|
getItemValue={item => item.value}
|
||||||
onChange={this.handleChange}
|
onChange={this.handleChange}
|
||||||
|
|
|
@ -28,7 +28,14 @@ export default class extends React.PureComponent<Props> {
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="yrbl-wrap">
|
<div className="yrbl-wrap">
|
||||||
<img alt="Friendly gerbil" className={classnames('yrbl', className)} src={image} />
|
<img
|
||||||
|
alt="Friendly gerbil"
|
||||||
|
className={classnames('yrbl', className)}
|
||||||
|
src={
|
||||||
|
// If we don't use a leading `/` @reach/router will try to append the src url to the existing web url
|
||||||
|
`/${image}`
|
||||||
|
}
|
||||||
|
/>
|
||||||
{title && subtitle && (
|
{title && subtitle && (
|
||||||
<div className="card__content">
|
<div className="card__content">
|
||||||
<h2 className="card__title">{title}</h2>
|
<h2 className="card__title">{title}</h2>
|
||||||
|
|
|
@ -48,3 +48,6 @@ export const UP = 'ChevronUp';
|
||||||
export const DOWN = 'ChevronDown';
|
export const DOWN = 'ChevronDown';
|
||||||
export const SECURE = 'Lock';
|
export const SECURE = 'Lock';
|
||||||
export const MENU = 'Menu';
|
export const MENU = 'Menu';
|
||||||
|
export const BACKUP = 'Database';
|
||||||
|
export const TRANSACTIONS = 'FileText';
|
||||||
|
export const LBRY = 'Lbry';
|
||||||
|
|
|
@ -1,8 +1,8 @@
|
||||||
import ErrorBoundary from 'component/errorBoundary';
|
import ErrorBoundary from 'component/errorBoundary';
|
||||||
import App from 'component/app';
|
import App from 'component/app';
|
||||||
import SnackBar from 'component/snackBar';
|
import SnackBar from 'component/snackBar';
|
||||||
import SplashScreen from 'component/splash';
|
|
||||||
// @if TARGET='app'
|
// @if TARGET='app'
|
||||||
|
import SplashScreen from 'component/splash';
|
||||||
import moment from 'moment';
|
import moment from 'moment';
|
||||||
import { ipcRenderer, remote, shell } from 'electron';
|
import { ipcRenderer, remote, shell } from 'electron';
|
||||||
import * as ACTIONS from 'constants/action_types';
|
import * as ACTIONS from 'constants/action_types';
|
||||||
|
@ -19,7 +19,6 @@ import {
|
||||||
doHideModal,
|
doHideModal,
|
||||||
} from 'redux/actions/app';
|
} from 'redux/actions/app';
|
||||||
import { Lbry, doToast, isURIValid, setSearchApi } from 'lbry-redux';
|
import { Lbry, doToast, isURIValid, setSearchApi } from 'lbry-redux';
|
||||||
import { doNavigate, doHistoryBack, doHistoryForward } from 'redux/actions/navigation';
|
|
||||||
import { doDownloadLanguages, doUpdateIsNightAsync } from 'redux/actions/settings';
|
import { doDownloadLanguages, doUpdateIsNightAsync } from 'redux/actions/settings';
|
||||||
import { doAuthenticate, Lbryio, rewards, doBlackListedOutpointsSubscribe } from 'lbryinc';
|
import { doAuthenticate, Lbryio, rewards, doBlackListedOutpointsSubscribe } from 'lbryinc';
|
||||||
import 'scss/all.scss';
|
import 'scss/all.scss';
|
||||||
|
@ -46,11 +45,11 @@ if (process.env.SEARCH_API_URL) {
|
||||||
|
|
||||||
// @if TARGET='app'
|
// @if TARGET='app'
|
||||||
ipcRenderer.on('navigate-backward', () => {
|
ipcRenderer.on('navigate-backward', () => {
|
||||||
app.store.dispatch(doHistoryBack());
|
// app.store.dispatch(doHistoryBack());
|
||||||
});
|
});
|
||||||
|
|
||||||
ipcRenderer.on('navigate-forward', () => {
|
ipcRenderer.on('navigate-forward', () => {
|
||||||
app.store.dispatch(doHistoryForward());
|
// app.store.dispatch(doHistoryForward());
|
||||||
});
|
});
|
||||||
// @endif
|
// @endif
|
||||||
|
|
||||||
|
@ -132,9 +131,9 @@ ipcRenderer.on('open-uri-requested', (event, uri, newSession) => {
|
||||||
app.store.dispatch(doConditionalAuthNavigate(newSession));
|
app.store.dispatch(doConditionalAuthNavigate(newSession));
|
||||||
} else if (uri.startsWith(APPPAGEURL)) {
|
} else if (uri.startsWith(APPPAGEURL)) {
|
||||||
const navpage = uri.replace(APPPAGEURL, '').toLowerCase();
|
const navpage = uri.replace(APPPAGEURL, '').toLowerCase();
|
||||||
app.store.dispatch(doNavigate(`/${navpage}`));
|
// app.store.dispatch(doNavigate(`/${navpage}`));
|
||||||
} else if (isURIValid(uri)) {
|
} else if (isURIValid(uri)) {
|
||||||
app.store.dispatch(doNavigate('/show', { uri }));
|
// app.store.dispatch(doNavigate('/show', { uri }));
|
||||||
} else {
|
} else {
|
||||||
app.store.dispatch(
|
app.store.dispatch(
|
||||||
doToast({
|
doToast({
|
||||||
|
@ -147,7 +146,7 @@ ipcRenderer.on('open-uri-requested', (event, uri, newSession) => {
|
||||||
|
|
||||||
ipcRenderer.on('open-menu', (event, uri) => {
|
ipcRenderer.on('open-menu', (event, uri) => {
|
||||||
if (uri && uri.startsWith('/help')) {
|
if (uri && uri.startsWith('/help')) {
|
||||||
app.store.dispatch(doNavigate('/help'));
|
// app.store.dispatch(doNavigate('/help'));
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -233,9 +232,11 @@ const init = () => {
|
||||||
app.store.dispatch(doBlackListedOutpointsSubscribe());
|
app.store.dispatch(doBlackListedOutpointsSubscribe());
|
||||||
|
|
||||||
function onDaemonReady() {
|
function onDaemonReady() {
|
||||||
|
// @if TARGET='app'
|
||||||
window.sessionStorage.setItem('loaded', 'y'); // once we've made it here once per session, we don't need to show splash again
|
window.sessionStorage.setItem('loaded', 'y'); // once we've made it here once per session, we don't need to show splash again
|
||||||
app.store.dispatch(doDaemonReady());
|
// @endif
|
||||||
|
|
||||||
|
app.store.dispatch(doDaemonReady());
|
||||||
ReactDOM.render(
|
ReactDOM.render(
|
||||||
<Provider store={store}>
|
<Provider store={store}>
|
||||||
<ErrorBoundary>
|
<ErrorBoundary>
|
||||||
|
@ -245,11 +246,9 @@ const init = () => {
|
||||||
</Provider>,
|
</Provider>,
|
||||||
document.getElementById('app')
|
document.getElementById('app')
|
||||||
);
|
);
|
||||||
// @if TARGET='web'
|
|
||||||
window.sessionStorage.removeItem('loaded');
|
|
||||||
// @endif
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// @if TARGET='app'
|
||||||
if (window.sessionStorage.getItem('loaded') === 'y') {
|
if (window.sessionStorage.getItem('loaded') === 'y') {
|
||||||
onDaemonReady();
|
onDaemonReady();
|
||||||
} else {
|
} else {
|
||||||
|
@ -263,6 +262,10 @@ const init = () => {
|
||||||
document.getElementById('app')
|
document.getElementById('app')
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
// @endif
|
||||||
|
// @if TARGET='web'
|
||||||
|
onDaemonReady();
|
||||||
|
// @endif
|
||||||
};
|
};
|
||||||
|
|
||||||
init();
|
init();
|
||||||
|
|
|
@ -1,11 +1,11 @@
|
||||||
import { connect } from 'react-redux';
|
import { connect } from 'react-redux';
|
||||||
import { doNavigate } from 'redux/actions/navigation';
|
|
||||||
import { doSetClientSetting } from 'redux/actions/settings';
|
import { doSetClientSetting } from 'redux/actions/settings';
|
||||||
import { selectUserIsRewardApproved, selectUnclaimedRewardValue } from 'lbryinc';
|
import { selectUserIsRewardApproved, selectUnclaimedRewardValue } from 'lbryinc';
|
||||||
import { selectBalance } from 'lbry-redux';
|
import { selectBalance } from 'lbry-redux';
|
||||||
import { doHideModal } from 'redux/actions/app';
|
import { doHideModal } from 'redux/actions/app';
|
||||||
import * as settings from 'constants/settings';
|
import * as settings from 'constants/settings';
|
||||||
import ModalCreditIntro from './view';
|
import ModalCreditIntro from './view';
|
||||||
|
import { navigate } from '@reach/router';
|
||||||
|
|
||||||
const select = state => ({
|
const select = state => ({
|
||||||
currentBalance: selectBalance(state),
|
currentBalance: selectBalance(state),
|
||||||
|
@ -15,8 +15,8 @@ const select = state => ({
|
||||||
|
|
||||||
const perform = dispatch => () => ({
|
const perform = dispatch => () => ({
|
||||||
addBalance: () => {
|
addBalance: () => {
|
||||||
|
navigate('/$/getcredits');
|
||||||
dispatch(doSetClientSetting(settings.CREDIT_REQUIRED_ACKNOWLEDGED, true));
|
dispatch(doSetClientSetting(settings.CREDIT_REQUIRED_ACKNOWLEDGED, true));
|
||||||
dispatch(doNavigate('/getcredits'));
|
|
||||||
dispatch(doHideModal());
|
dispatch(doHideModal());
|
||||||
},
|
},
|
||||||
closeModal: () => {
|
closeModal: () => {
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
// @flow
|
// @flow
|
||||||
import React from 'react';
|
import React from 'react';
|
||||||
import { Modal } from 'modal/modal';
|
import { Modal } from 'modal/modal';
|
||||||
|
import { formatLbryUriForWeb } from 'util/uri';
|
||||||
// @if TARGET='app'
|
// @if TARGET='app'
|
||||||
import { shell } from 'electron';
|
import { shell } from 'electron';
|
||||||
// @endif
|
// @endif
|
||||||
|
@ -13,10 +14,16 @@ type Props = {
|
||||||
class ModalOpenExternalLink extends React.PureComponent<Props> {
|
class ModalOpenExternalLink extends React.PureComponent<Props> {
|
||||||
openExternalLink() {
|
openExternalLink() {
|
||||||
const { uri, closeModal } = this.props;
|
const { uri, closeModal } = this.props;
|
||||||
|
// @if TARGET='app'
|
||||||
const { openExternal } = shell;
|
const { openExternal } = shell;
|
||||||
if (uri) {
|
if (uri) {
|
||||||
openExternal(uri);
|
openExternal(uri);
|
||||||
}
|
}
|
||||||
|
// @endif
|
||||||
|
// @if TARGET='web'
|
||||||
|
window.open(uri);
|
||||||
|
// @endif
|
||||||
|
|
||||||
closeModal();
|
closeModal();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
import { connect } from 'react-redux';
|
import { connect } from 'react-redux';
|
||||||
import { doHideModal } from 'redux/actions/app';
|
import { doHideModal } from 'redux/actions/app';
|
||||||
import { selectPhoneToVerify, selectUser } from 'lbryinc';
|
import { selectPhoneToVerify, selectUser } from 'lbryinc';
|
||||||
import { doNavigate } from 'redux/actions/navigation';
|
import { navigate } from '@reach/router';
|
||||||
import ModalPhoneCollection from './view';
|
import ModalPhoneCollection from './view';
|
||||||
|
|
||||||
const select = state => ({
|
const select = state => ({
|
||||||
|
@ -12,7 +12,7 @@ const select = state => ({
|
||||||
const perform = dispatch => () => ({
|
const perform = dispatch => () => ({
|
||||||
closeModal: () => {
|
closeModal: () => {
|
||||||
dispatch(doHideModal());
|
dispatch(doHideModal());
|
||||||
dispatch(doNavigate('/rewards'));
|
navigate('/$/rewards');
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
|
@ -2,12 +2,10 @@ import { connect } from 'react-redux';
|
||||||
import { doHideModal } from 'redux/actions/app';
|
import { doHideModal } from 'redux/actions/app';
|
||||||
import ModalSendTip from './view';
|
import ModalSendTip from './view';
|
||||||
import { doClearPublish } from 'redux/actions/publish';
|
import { doClearPublish } from 'redux/actions/publish';
|
||||||
import { doNavigate } from 'redux/actions/navigation';
|
|
||||||
|
|
||||||
const perform = dispatch => ({
|
const perform = dispatch => ({
|
||||||
closeModal: () => dispatch(doHideModal()),
|
closeModal: () => dispatch(doHideModal()),
|
||||||
clearPublish: () => dispatch(doClearPublish()),
|
clearPublish: () => dispatch(doClearPublish()),
|
||||||
navigate: (path, params) => dispatch(doNavigate(path, params)),
|
|
||||||
});
|
});
|
||||||
|
|
||||||
export default connect(
|
export default connect(
|
||||||
|
|
|
@ -1,20 +1,15 @@
|
||||||
import { connect } from 'react-redux';
|
import { connect } from 'react-redux';
|
||||||
import * as settings from 'constants/settings';
|
import * as settings from 'constants/settings';
|
||||||
import { selectBalance, selectCurrentPage, selectError, doToast } from 'lbry-redux';
|
import { selectBalance, makeSelectCostInfoForUri, selectError, doToast } from 'lbry-redux';
|
||||||
import { makeSelectClientSetting } from 'redux/selectors/settings';
|
import { makeSelectClientSetting } from 'redux/selectors/settings';
|
||||||
import {
|
import { selectUser, selectUserIsVerificationCandidate } from 'lbryinc';
|
||||||
selectUser,
|
|
||||||
selectUserIsVerificationCandidate,
|
|
||||||
selectCostForCurrentPageUri,
|
|
||||||
} from 'lbryinc';
|
|
||||||
import { selectModal } from 'redux/selectors/app';
|
import { selectModal } from 'redux/selectors/app';
|
||||||
import { doOpenModal } from 'redux/actions/app';
|
import { doOpenModal } from 'redux/actions/app';
|
||||||
import ModalRouter from './view';
|
import ModalRouter from './view';
|
||||||
|
|
||||||
const select = state => ({
|
const select = (state, props) => ({
|
||||||
balance: selectBalance(state),
|
balance: selectBalance(state),
|
||||||
showPageCost: selectCostForCurrentPageUri(state),
|
showPageCost: makeSelectCostInfoForUri(props.uri)(state),
|
||||||
page: selectCurrentPage(state),
|
|
||||||
isVerificationCandidate: selectUserIsVerificationCandidate(state),
|
isVerificationCandidate: selectUserIsVerificationCandidate(state),
|
||||||
isCreditIntroAcknowledged: makeSelectClientSetting(settings.CREDIT_REQUIRED_ACKNOWLEDGED)(state),
|
isCreditIntroAcknowledged: makeSelectClientSetting(settings.CREDIT_REQUIRED_ACKNOWLEDGED)(state),
|
||||||
isEmailCollectionAcknowledged: makeSelectClientSetting(settings.EMAIL_COLLECTION_ACKNOWLEDGED)(
|
isEmailCollectionAcknowledged: makeSelectClientSetting(settings.EMAIL_COLLECTION_ACKNOWLEDGED)(
|
||||||
|
|
|
@ -113,6 +113,7 @@ class ModalRouter extends React.PureComponent<Props, State> {
|
||||||
|
|
||||||
isPaidShowPage(props: Props) {
|
isPaidShowPage(props: Props) {
|
||||||
const { page, showPageCost } = props;
|
const { page, showPageCost } = props;
|
||||||
|
// Fix me
|
||||||
return page === 'show' && showPageCost > 0;
|
return page === 'show' && showPageCost > 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,6 +1,4 @@
|
||||||
import { selectPathAfterAuth } from 'lbry-redux';
|
|
||||||
import { connect } from 'react-redux';
|
import { connect } from 'react-redux';
|
||||||
import { doNavigate } from 'redux/actions/navigation';
|
|
||||||
import {
|
import {
|
||||||
selectAuthenticationIsPending,
|
selectAuthenticationIsPending,
|
||||||
selectEmailToVerify,
|
selectEmailToVerify,
|
||||||
|
@ -17,16 +15,11 @@ const select = state => ({
|
||||||
selectUserIsPending(state) ||
|
selectUserIsPending(state) ||
|
||||||
selectIdentityVerifyIsPending(state),
|
selectIdentityVerifyIsPending(state),
|
||||||
email: selectEmailToVerify(state),
|
email: selectEmailToVerify(state),
|
||||||
pathAfterAuth: selectPathAfterAuth(state),
|
|
||||||
user: selectUser(state),
|
user: selectUser(state),
|
||||||
isVerificationCandidate: selectUserIsVerificationCandidate(state),
|
isVerificationCandidate: selectUserIsVerificationCandidate(state),
|
||||||
});
|
});
|
||||||
|
|
||||||
const perform = dispatch => ({
|
|
||||||
navigate: path => dispatch(doNavigate(path)),
|
|
||||||
});
|
|
||||||
|
|
||||||
export default connect(
|
export default connect(
|
||||||
select,
|
select,
|
||||||
perform
|
null
|
||||||
)(AuthPage);
|
)(AuthPage);
|
||||||
|
|
|
@ -1,4 +1,5 @@
|
||||||
// @flow
|
// @flow
|
||||||
|
import type { UrlLocation } from 'types/location';
|
||||||
import React from 'react';
|
import React from 'react';
|
||||||
import BusyIndicator from 'component/common/busy-indicator';
|
import BusyIndicator from 'component/common/busy-indicator';
|
||||||
import Button from 'component/button';
|
import Button from 'component/button';
|
||||||
|
@ -6,17 +7,18 @@ import UserEmailNew from 'component/userEmailNew';
|
||||||
import UserEmailVerify from 'component/userEmailVerify';
|
import UserEmailVerify from 'component/userEmailVerify';
|
||||||
import UserVerify from 'component/userVerify';
|
import UserVerify from 'component/userVerify';
|
||||||
import Page from 'component/page';
|
import Page from 'component/page';
|
||||||
|
import { navigate } from '@reach/router';
|
||||||
|
|
||||||
type Props = {
|
type Props = {
|
||||||
isPending: boolean,
|
isPending: boolean,
|
||||||
email: string,
|
email: string,
|
||||||
pathAfterAuth: string,
|
pathAfterAuth: string,
|
||||||
|
location: UrlLocation,
|
||||||
user: ?{
|
user: ?{
|
||||||
has_verified_email: boolean,
|
has_verified_email: boolean,
|
||||||
is_reward_approved: boolean,
|
is_reward_approved: boolean,
|
||||||
is_identity_verified: boolean,
|
is_identity_verified: boolean,
|
||||||
},
|
},
|
||||||
navigate: (string, ?{}) => void,
|
|
||||||
};
|
};
|
||||||
|
|
||||||
class AuthPage extends React.PureComponent<Props> {
|
class AuthPage extends React.PureComponent<Props> {
|
||||||
|
@ -29,14 +31,18 @@ class AuthPage extends React.PureComponent<Props> {
|
||||||
}
|
}
|
||||||
|
|
||||||
navigateIfAuthenticated = (props: Props) => {
|
navigateIfAuthenticated = (props: Props) => {
|
||||||
const { isPending, user, pathAfterAuth, navigate } = props;
|
const { isPending, user, location } = props;
|
||||||
if (
|
if (
|
||||||
!isPending &&
|
!isPending &&
|
||||||
user &&
|
user &&
|
||||||
user.has_verified_email &&
|
user.has_verified_email &&
|
||||||
(user.is_reward_approved || user.is_identity_verified)
|
(user.is_reward_approved || user.is_identity_verified)
|
||||||
) {
|
) {
|
||||||
navigate(pathAfterAuth);
|
const { search } = location;
|
||||||
|
const urlParams = new URLSearchParams(search);
|
||||||
|
const redirectTo = urlParams.get('redirect');
|
||||||
|
const path = redirectTo ? `/$/${redirectTo}` : '/';
|
||||||
|
navigate(path);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -56,7 +62,6 @@ class AuthPage extends React.PureComponent<Props> {
|
||||||
}
|
}
|
||||||
|
|
||||||
render() {
|
render() {
|
||||||
const { navigate } = this.props;
|
|
||||||
const [innerContent, useTemplate] = this.renderMain();
|
const [innerContent, useTemplate] = this.renderMain();
|
||||||
|
|
||||||
return (
|
return (
|
||||||
|
@ -69,11 +74,7 @@ class AuthPage extends React.PureComponent<Props> {
|
||||||
{`${__(
|
{`${__(
|
||||||
'This information is disclosed only to LBRY, Inc. and not to the LBRY network. It is only required to earn LBRY rewards and may be used to sync usage data across devices.'
|
'This information is disclosed only to LBRY, Inc. and not to the LBRY network. It is only required to earn LBRY rewards and may be used to sync usage data across devices.'
|
||||||
)} `}
|
)} `}
|
||||||
<Button
|
<Button button="link" navigate="/" label={__('Return home.')} />
|
||||||
button="link"
|
|
||||||
onClick={() => navigate('/discover')}
|
|
||||||
label={__('Return home.')}
|
|
||||||
/>
|
|
||||||
</p>
|
</p>
|
||||||
</section>
|
</section>
|
||||||
) : (
|
) : (
|
||||||
|
|
|
@ -3,30 +3,24 @@ import { doFetchClaimsByChannel } from 'redux/actions/content';
|
||||||
import { PAGE_SIZE } from 'constants/claim';
|
import { PAGE_SIZE } from 'constants/claim';
|
||||||
import {
|
import {
|
||||||
makeSelectClaimForUri,
|
makeSelectClaimForUri,
|
||||||
makeSelectClaimsInChannelForCurrentPage,
|
makeSelectClaimsInChannelForCurrentPageState,
|
||||||
makeSelectFetchingChannelClaims,
|
makeSelectFetchingChannelClaims,
|
||||||
makeSelectCurrentParam,
|
|
||||||
makeSelectClaimIsMine,
|
makeSelectClaimIsMine,
|
||||||
makeSelectTotalPagesForChannel,
|
makeSelectTotalPagesForChannel,
|
||||||
selectCurrentParams,
|
|
||||||
} from 'lbry-redux';
|
} from 'lbry-redux';
|
||||||
import { doNavigate } from 'redux/actions/navigation';
|
|
||||||
import { doOpenModal } from 'redux/actions/app';
|
import { doOpenModal } from 'redux/actions/app';
|
||||||
import ChannelPage from './view';
|
import ChannelPage from './view';
|
||||||
|
|
||||||
const select = (state, props) => ({
|
const select = (state, props) => ({
|
||||||
claim: makeSelectClaimForUri(props.uri)(state),
|
claim: makeSelectClaimForUri(props.uri)(state),
|
||||||
claimsInChannel: makeSelectClaimsInChannelForCurrentPage(props.uri)(state),
|
claimsInChannel: makeSelectClaimsInChannelForCurrentPageState(props.uri)(state),
|
||||||
fetching: makeSelectFetchingChannelClaims(props.uri)(state),
|
fetching: makeSelectFetchingChannelClaims(props.uri)(state),
|
||||||
page: makeSelectCurrentParam('page')(state),
|
|
||||||
params: selectCurrentParams(state),
|
|
||||||
totalPages: makeSelectTotalPagesForChannel(props.uri, PAGE_SIZE)(state),
|
totalPages: makeSelectTotalPagesForChannel(props.uri, PAGE_SIZE)(state),
|
||||||
channelIsMine: makeSelectClaimIsMine(props.uri)(state),
|
channelIsMine: makeSelectClaimIsMine(props.uri)(state),
|
||||||
});
|
});
|
||||||
|
|
||||||
const perform = dispatch => ({
|
const perform = dispatch => ({
|
||||||
fetchClaims: (uri, page) => dispatch(doFetchClaimsByChannel(uri, page)),
|
fetchClaims: (uri, page) => dispatch(doFetchClaimsByChannel(uri, page)),
|
||||||
navigate: (path, params) => dispatch(doNavigate(path, params)),
|
|
||||||
openModal: (modal, props) => dispatch(doOpenModal(modal, props)),
|
openModal: (modal, props) => dispatch(doOpenModal(modal, props)),
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
|
@ -1,8 +1,9 @@
|
||||||
// @flow
|
// @flow
|
||||||
import type { Claim } from 'types/claim';
|
import type { Claim } from 'types/claim';
|
||||||
|
import type { UrlLocation } from 'types/location';
|
||||||
import * as icons from 'constants/icons';
|
import * as icons from 'constants/icons';
|
||||||
import * as MODALS from 'constants/modal_types';
|
import * as MODALS from 'constants/modal_types';
|
||||||
import React from 'react';
|
import React, { useEffect } from 'react';
|
||||||
import BusyIndicator from 'component/common/busy-indicator';
|
import BusyIndicator from 'component/common/busy-indicator';
|
||||||
import { FormField, Form } from 'component/common/form';
|
import { FormField, Form } from 'component/common/form';
|
||||||
import ReactPaginate from 'react-paginate';
|
import ReactPaginate from 'react-paginate';
|
||||||
|
@ -11,10 +12,10 @@ import Page from 'component/page';
|
||||||
import FileList from 'component/fileList';
|
import FileList from 'component/fileList';
|
||||||
import HiddenNsfwClaims from 'component/hiddenNsfwClaims';
|
import HiddenNsfwClaims from 'component/hiddenNsfwClaims';
|
||||||
import Button from 'component/button';
|
import Button from 'component/button';
|
||||||
|
import { navigate } from '@reach/router';
|
||||||
|
|
||||||
type Props = {
|
type Props = {
|
||||||
uri: string,
|
uri: string,
|
||||||
page: number,
|
|
||||||
totalPages: number,
|
totalPages: number,
|
||||||
fetching: boolean,
|
fetching: boolean,
|
||||||
params: { page: number },
|
params: { page: number },
|
||||||
|
@ -24,32 +25,42 @@ type Props = {
|
||||||
fetchClaims: (string, number) => void,
|
fetchClaims: (string, number) => void,
|
||||||
navigate: (string, {}) => void,
|
navigate: (string, {}) => void,
|
||||||
openModal: (id: string, { uri: string }) => void,
|
openModal: (id: string, { uri: string }) => void,
|
||||||
|
location: UrlLocation,
|
||||||
};
|
};
|
||||||
|
|
||||||
class ChannelPage extends React.PureComponent<Props> {
|
function ChannelPage(props: Props) {
|
||||||
componentDidMount() {
|
const {
|
||||||
const { uri, page, fetchClaims } = this.props;
|
uri,
|
||||||
fetchClaims(uri, page || 1);
|
fetching,
|
||||||
}
|
claimsInChannel,
|
||||||
|
claim,
|
||||||
|
totalPages,
|
||||||
|
channelIsMine,
|
||||||
|
openModal,
|
||||||
|
fetchClaims,
|
||||||
|
location,
|
||||||
|
} = props;
|
||||||
|
|
||||||
componentDidUpdate(prevProps: Props) {
|
const { name, permanent_url: permanentUrl } = claim;
|
||||||
const { page, fetchClaims, uri } = this.props;
|
const { search } = location;
|
||||||
|
const urlParams = new URLSearchParams(search);
|
||||||
|
const page = Number(urlParams.get('page')) || 1;
|
||||||
|
|
||||||
if (prevProps.page && prevProps.page && page !== prevProps.page) {
|
useEffect(() => {
|
||||||
fetchClaims(uri, page);
|
// Fetch new claims if the channel or page number changes
|
||||||
|
fetchClaims(uri, page);
|
||||||
|
}, [uri, page]);
|
||||||
|
|
||||||
|
const changePage = (pageNumber: number) => {
|
||||||
|
if (!page && pageNumber === 1) {
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
changePage(pageNumber: number) {
|
navigate(`?page=${pageNumber}`);
|
||||||
const { params } = this.props;
|
};
|
||||||
const newParams = Object.assign({}, params, { page: pageNumber });
|
|
||||||
|
|
||||||
this.props.navigate('/show', newParams);
|
const paginate = (e: SyntheticKeyboardEvent<*>) => {
|
||||||
}
|
// Change page if enter was pressed, and the given page is between the first and the last page
|
||||||
|
|
||||||
paginate(e: SyntheticKeyboardEvent<*>, totalPages: number) {
|
|
||||||
// Change page if enter was pressed, and the given page is between
|
|
||||||
// the first and the last.
|
|
||||||
const pageFromInput = Number(e.currentTarget.value);
|
const pageFromInput = Number(e.currentTarget.value);
|
||||||
|
|
||||||
if (
|
if (
|
||||||
|
@ -59,90 +70,77 @@ class ChannelPage extends React.PureComponent<Props> {
|
||||||
pageFromInput > 0 &&
|
pageFromInput > 0 &&
|
||||||
pageFromInput <= totalPages
|
pageFromInput <= totalPages
|
||||||
) {
|
) {
|
||||||
this.changePage(pageFromInput);
|
changePage(pageFromInput);
|
||||||
}
|
}
|
||||||
}
|
};
|
||||||
|
|
||||||
render() {
|
return (
|
||||||
const {
|
<Page notContained>
|
||||||
uri,
|
<header className="channel-info">
|
||||||
fetching,
|
<h1 className="media__title media__title--large">
|
||||||
claimsInChannel,
|
{name}
|
||||||
claim,
|
{fetching && <BusyIndicator />}
|
||||||
page,
|
</h1>
|
||||||
totalPages,
|
<span>{`lbry://${permanentUrl}`}</span>
|
||||||
channelIsMine,
|
|
||||||
openModal,
|
|
||||||
} = this.props;
|
|
||||||
const { name, permanent_url: permanentUrl } = claim;
|
|
||||||
const currentPage = parseInt((page || 1) - 1, 10);
|
|
||||||
const contentList =
|
|
||||||
claimsInChannel && claimsInChannel.length ? (
|
|
||||||
<FileList sortByHeight hideFilter fileInfos={claimsInChannel} />
|
|
||||||
) : (
|
|
||||||
!fetching && <span className="empty">{__('No content found.')}</span>
|
|
||||||
);
|
|
||||||
|
|
||||||
return (
|
<div className="channel-info__actions__group">
|
||||||
<Page notContained>
|
<SubscribeButton uri={`lbry://${permanentUrl}`} channelName={name} />
|
||||||
<header className="channel-info">
|
<Button
|
||||||
<h1 className="media__title media__title--large">
|
button="alt"
|
||||||
{name}
|
icon={icons.SHARE}
|
||||||
{fetching && <BusyIndicator />}
|
label={__('Share Channel')}
|
||||||
</h1>
|
onClick={() =>
|
||||||
|
openModal(MODALS.SOCIAL_SHARE, { uri, speechShareable: true, isChannel: true })
|
||||||
|
}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
</header>
|
||||||
|
|
||||||
<div className="channel-info__actions__group">
|
<section className="media-group--list">
|
||||||
<SubscribeButton uri={`lbry://${permanentUrl}`} channelName={name} />
|
{claimsInChannel && claimsInChannel.length ? (
|
||||||
<Button
|
<FileList sortByHeight hideFilter fileInfos={claimsInChannel} />
|
||||||
button="alt"
|
) : (
|
||||||
icon={icons.SHARE}
|
!fetching && <span className="empty">{__('No content found.')}</span>
|
||||||
label={__('Share Channel')}
|
|
||||||
onClick={() =>
|
|
||||||
openModal(MODALS.SOCIAL_SHARE, { uri, speechShareable: true, isChannel: true })
|
|
||||||
}
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
</header>
|
|
||||||
|
|
||||||
<section className="media-group--list">{contentList}</section>
|
|
||||||
|
|
||||||
{(!fetching || (claimsInChannel && claimsInChannel.length)) && totalPages > 1 && (
|
|
||||||
<Form>
|
|
||||||
<fieldset-group class="fieldset-group--smushed fieldgroup--paginate">
|
|
||||||
<fieldset-section>
|
|
||||||
<ReactPaginate
|
|
||||||
pageCount={totalPages}
|
|
||||||
pageRangeDisplayed={2}
|
|
||||||
previousLabel="‹"
|
|
||||||
nextLabel="›"
|
|
||||||
activeClassName="pagination__item--selected"
|
|
||||||
pageClassName="pagination__item"
|
|
||||||
previousClassName="pagination__item pagination__item--previous"
|
|
||||||
nextClassName="pagination__item pagination__item--next"
|
|
||||||
breakClassName="pagination__item pagination__item--break"
|
|
||||||
marginPagesDisplayed={2}
|
|
||||||
onPageChange={e => this.changePage(e.selected + 1)}
|
|
||||||
forcePage={currentPage}
|
|
||||||
initialPage={currentPage}
|
|
||||||
containerClassName="pagination"
|
|
||||||
/>
|
|
||||||
</fieldset-section>
|
|
||||||
|
|
||||||
<FormField
|
|
||||||
className="paginate-channel"
|
|
||||||
onKeyUp={e => this.paginate(e, totalPages)}
|
|
||||||
label={__('Go to page:')}
|
|
||||||
type="text"
|
|
||||||
name="paginate-file"
|
|
||||||
/>
|
|
||||||
</fieldset-group>
|
|
||||||
</Form>
|
|
||||||
)}
|
)}
|
||||||
|
</section>
|
||||||
|
|
||||||
{!channelIsMine && <HiddenNsfwClaims className="card__content help" uri={uri} />}
|
{(!fetching || (claimsInChannel && claimsInChannel.length)) && totalPages > 1 && (
|
||||||
</Page>
|
<Form>
|
||||||
);
|
<fieldset-group class="fieldset-group--smushed fieldgroup--paginate">
|
||||||
}
|
<fieldset-section>
|
||||||
|
<ReactPaginate
|
||||||
|
pageCount={totalPages}
|
||||||
|
pageRangeDisplayed={2}
|
||||||
|
previousLabel="‹"
|
||||||
|
nextLabel="›"
|
||||||
|
activeClassName="pagination__item--selected"
|
||||||
|
pageClassName="pagination__item"
|
||||||
|
previousClassName="pagination__item pagination__item--previous"
|
||||||
|
nextClassName="pagination__item pagination__item--next"
|
||||||
|
breakClassName="pagination__item pagination__item--break"
|
||||||
|
marginPagesDisplayed={2}
|
||||||
|
onPageChange={e => changePage(e.selected + 1)}
|
||||||
|
forcePage={page - 1}
|
||||||
|
initialPage={page - 1}
|
||||||
|
disableInitialCallback
|
||||||
|
containerClassName="pagination"
|
||||||
|
/>
|
||||||
|
</fieldset-section>
|
||||||
|
|
||||||
|
<FormField
|
||||||
|
className="paginate-channel"
|
||||||
|
onKeyUp={e => paginate(e)}
|
||||||
|
label={__('Go to page:')}
|
||||||
|
type="text"
|
||||||
|
name="paginate-file"
|
||||||
|
/>
|
||||||
|
</fieldset-group>
|
||||||
|
</Form>
|
||||||
|
)}
|
||||||
|
|
||||||
|
{!channelIsMine && <HiddenNsfwClaims className="card__content help" uri={uri} />}
|
||||||
|
</Page>
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
export default ChannelPage;
|
export default ChannelPage;
|
||||||
|
|
|
@ -14,7 +14,7 @@ const select = state => ({
|
||||||
});
|
});
|
||||||
|
|
||||||
const perform = dispatch => ({
|
const perform = dispatch => ({
|
||||||
fetchFeaturedUris: () => dispatch(doFetchFeaturedUris(true)),
|
fetchFeaturedUris: () => dispatch(doFetchFeaturedUris()),
|
||||||
fetchRewardedContent: () => dispatch(doFetchRewardedContent()),
|
fetchRewardedContent: () => dispatch(doFetchRewardedContent()),
|
||||||
fetchRewards: () => dispatch(doRewardList()),
|
fetchRewards: () => dispatch(doRewardList()),
|
||||||
});
|
});
|
||||||
|
|
|
@ -1,6 +1,5 @@
|
||||||
import { connect } from 'react-redux';
|
import { connect } from 'react-redux';
|
||||||
import * as settings from 'constants/settings';
|
import * as settings from 'constants/settings';
|
||||||
import { doNavigate } from 'redux/actions/navigation';
|
|
||||||
import { selectRewardContentClaimIds, selectPlayingUri } from 'redux/selectors/content';
|
import { selectRewardContentClaimIds, selectPlayingUri } from 'redux/selectors/content';
|
||||||
import { doRemoveUnreadSubscription } from 'redux/actions/subscriptions';
|
import { doRemoveUnreadSubscription } from 'redux/actions/subscriptions';
|
||||||
import { doSetClientSetting } from 'redux/actions/settings';
|
import { doSetClientSetting } from 'redux/actions/settings';
|
||||||
|
@ -15,10 +14,10 @@ import {
|
||||||
makeSelectChannelForClaimUri,
|
makeSelectChannelForClaimUri,
|
||||||
} from 'lbry-redux';
|
} from 'lbry-redux';
|
||||||
import {
|
import {
|
||||||
makeSelectCostInfoForUri,
|
|
||||||
doFetchCostInfoForUri,
|
|
||||||
doFetchViewCount,
|
doFetchViewCount,
|
||||||
makeSelectViewCountForUri,
|
makeSelectViewCountForUri,
|
||||||
|
makeSelectCostInfoForUri,
|
||||||
|
doFetchCostInfoForUri,
|
||||||
} from 'lbryinc';
|
} from 'lbryinc';
|
||||||
import { selectShowNsfw, makeSelectClientSetting } from 'redux/selectors/settings';
|
import { selectShowNsfw, makeSelectClientSetting } from 'redux/selectors/settings';
|
||||||
import { makeSelectIsSubscribed } from 'redux/selectors/subscriptions';
|
import { makeSelectIsSubscribed } from 'redux/selectors/subscriptions';
|
||||||
|
@ -43,7 +42,6 @@ const select = (state, props) => ({
|
||||||
});
|
});
|
||||||
|
|
||||||
const perform = dispatch => ({
|
const perform = dispatch => ({
|
||||||
navigate: (path, params) => dispatch(doNavigate(path, params)),
|
|
||||||
fetchFileInfo: uri => dispatch(doFetchFileInfo(uri)),
|
fetchFileInfo: uri => dispatch(doFetchFileInfo(uri)),
|
||||||
fetchCostInfo: uri => dispatch(doFetchCostInfoForUri(uri)),
|
fetchCostInfo: uri => dispatch(doFetchCostInfoForUri(uri)),
|
||||||
openModal: (modal, props) => dispatch(doOpenModal(modal, props)),
|
openModal: (modal, props) => dispatch(doOpenModal(modal, props)),
|
||||||
|
|
|
@ -39,7 +39,6 @@ type Props = {
|
||||||
channelUri: string,
|
channelUri: string,
|
||||||
viewCount: number,
|
viewCount: number,
|
||||||
prepareEdit: ({}, string) => void,
|
prepareEdit: ({}, string) => void,
|
||||||
navigate: (string, ?{}) => void,
|
|
||||||
openModal: (id: string, { uri: string }) => void,
|
openModal: (id: string, { uri: string }) => void,
|
||||||
markSubscriptionRead: (string, string) => void,
|
markSubscriptionRead: (string, string) => void,
|
||||||
fetchViewCount: string => void,
|
fetchViewCount: string => void,
|
||||||
|
@ -132,7 +131,6 @@ class FilePage extends React.Component<Props> {
|
||||||
openModal,
|
openModal,
|
||||||
claimIsMine,
|
claimIsMine,
|
||||||
prepareEdit,
|
prepareEdit,
|
||||||
navigate,
|
|
||||||
costInfo,
|
costInfo,
|
||||||
fileInfo,
|
fileInfo,
|
||||||
channelUri,
|
channelUri,
|
||||||
|
@ -173,6 +171,7 @@ class FilePage extends React.Component<Props> {
|
||||||
return (
|
return (
|
||||||
<Page notContained className="main--file-page">
|
<Page notContained className="main--file-page">
|
||||||
<div className="grid-area--content">
|
<div className="grid-area--content">
|
||||||
|
<h1 className="media__uri">{uri}</h1>
|
||||||
{showFile && <FileViewer className="content__embedded" uri={uri} mediaType={mediaType} />}
|
{showFile && <FileViewer className="content__embedded" uri={uri} mediaType={mediaType} />}
|
||||||
{!showFile &&
|
{!showFile &&
|
||||||
(thumbnail ? (
|
(thumbnail ? (
|
||||||
|
@ -231,9 +230,9 @@ class FilePage extends React.Component<Props> {
|
||||||
button="primary"
|
button="primary"
|
||||||
icon={icons.EDIT}
|
icon={icons.EDIT}
|
||||||
label={__('Edit')}
|
label={__('Edit')}
|
||||||
|
navigate="/$/publish"
|
||||||
onClick={() => {
|
onClick={() => {
|
||||||
prepareEdit(claim, editUri);
|
prepareEdit(claim, editUri);
|
||||||
navigate('/publish');
|
|
||||||
}}
|
}}
|
||||||
/>
|
/>
|
||||||
)}
|
)}
|
||||||
|
|
|
@ -5,7 +5,6 @@ import {
|
||||||
selectIsFetchingFileList,
|
selectIsFetchingFileList,
|
||||||
selectFileListDownloadedSort,
|
selectFileListDownloadedSort,
|
||||||
} from 'lbry-redux';
|
} from 'lbry-redux';
|
||||||
import { doNavigate } from 'redux/actions/navigation';
|
|
||||||
import FileListDownloaded from './view';
|
import FileListDownloaded from './view';
|
||||||
|
|
||||||
const select = state => ({
|
const select = state => ({
|
||||||
|
@ -15,11 +14,7 @@ const select = state => ({
|
||||||
sortBy: selectFileListDownloadedSort(state),
|
sortBy: selectFileListDownloadedSort(state),
|
||||||
});
|
});
|
||||||
|
|
||||||
const perform = dispatch => ({
|
|
||||||
navigate: path => dispatch(doNavigate(path)),
|
|
||||||
});
|
|
||||||
|
|
||||||
export default connect(
|
export default connect(
|
||||||
select,
|
select,
|
||||||
perform
|
null
|
||||||
)(FileListDownloaded);
|
)(FileListDownloaded);
|
||||||
|
|
|
@ -8,13 +8,12 @@ import { PAGES } from 'lbry-redux';
|
||||||
type Props = {
|
type Props = {
|
||||||
fetching: boolean,
|
fetching: boolean,
|
||||||
fileInfos: {},
|
fileInfos: {},
|
||||||
navigate: (string, ?{}) => void,
|
|
||||||
sortBy: string,
|
sortBy: string,
|
||||||
};
|
};
|
||||||
|
|
||||||
class FileListDownloaded extends React.PureComponent<Props> {
|
class FileListDownloaded extends React.PureComponent<Props> {
|
||||||
render() {
|
render() {
|
||||||
const { fetching, fileInfos, navigate, sortBy } = this.props;
|
const { fetching, fileInfos, sortBy } = this.props;
|
||||||
const hasDownloads = fileInfos && Object.values(fileInfos).length > 0;
|
const hasDownloads = fileInfos && Object.values(fileInfos).length > 0;
|
||||||
|
|
||||||
return (
|
return (
|
||||||
|
@ -32,11 +31,7 @@ class FileListDownloaded extends React.PureComponent<Props> {
|
||||||
|
|
||||||
<div className="card__content">
|
<div className="card__content">
|
||||||
<div className="card__actions card__actions--center">
|
<div className="card__actions card__actions--center">
|
||||||
<Button
|
<Button button="primary" navigate="/" label={__('Explore new content')} />
|
||||||
button="primary"
|
|
||||||
onClick={() => navigate('/discover')}
|
|
||||||
label={__('Explore new content')}
|
|
||||||
/>
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</section>
|
</section>
|
||||||
|
|
|
@ -4,7 +4,6 @@ import {
|
||||||
selectFileListPublishedSort,
|
selectFileListPublishedSort,
|
||||||
selectMyClaimsWithoutChannels,
|
selectMyClaimsWithoutChannels,
|
||||||
} from 'lbry-redux';
|
} from 'lbry-redux';
|
||||||
import { doNavigate } from 'redux/actions/navigation';
|
|
||||||
import { doCheckPendingPublishes } from 'redux/actions/publish';
|
import { doCheckPendingPublishes } from 'redux/actions/publish';
|
||||||
import FileListPublished from './view';
|
import FileListPublished from './view';
|
||||||
|
|
||||||
|
@ -15,7 +14,6 @@ const select = state => ({
|
||||||
});
|
});
|
||||||
|
|
||||||
const perform = dispatch => ({
|
const perform = dispatch => ({
|
||||||
navigate: path => dispatch(doNavigate(path)),
|
|
||||||
checkPendingPublishes: () => dispatch(doCheckPendingPublishes()),
|
checkPendingPublishes: () => dispatch(doCheckPendingPublishes()),
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
|
@ -9,7 +9,6 @@ import { PAGES } from 'lbry-redux';
|
||||||
type Props = {
|
type Props = {
|
||||||
claims: Array<Claim>,
|
claims: Array<Claim>,
|
||||||
checkPendingPublishes: () => void,
|
checkPendingPublishes: () => void,
|
||||||
navigate: (string, ?{}) => void,
|
|
||||||
fetching: boolean,
|
fetching: boolean,
|
||||||
sortBy: string,
|
sortBy: string,
|
||||||
};
|
};
|
||||||
|
@ -21,7 +20,7 @@ class FileListPublished extends React.PureComponent<Props> {
|
||||||
}
|
}
|
||||||
|
|
||||||
render() {
|
render() {
|
||||||
const { fetching, claims, navigate, sortBy } = this.props;
|
const { fetching, claims, sortBy } = this.props;
|
||||||
return (
|
return (
|
||||||
<Page notContained loading={fetching}>
|
<Page notContained loading={fetching}>
|
||||||
{claims && claims.length ? (
|
{claims && claims.length ? (
|
||||||
|
@ -45,7 +44,7 @@ class FileListPublished extends React.PureComponent<Props> {
|
||||||
<div className="card__actions card__actions--center">
|
<div className="card__actions card__actions--center">
|
||||||
<Button
|
<Button
|
||||||
button="primary"
|
button="primary"
|
||||||
onClick={() => navigate('/publish')}
|
navigate="/$/publish"
|
||||||
label={__('Publish something new')}
|
label={__('Publish something new')}
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
@ -200,7 +200,7 @@ class HelpPage extends React.PureComponent<Props, State> {
|
||||||
<div className="card__content">
|
<div className="card__content">
|
||||||
<div className="card__actions">
|
<div className="card__actions">
|
||||||
<Button
|
<Button
|
||||||
navigate="/report"
|
navigate="/$/report"
|
||||||
label={__('Submit a Bug Report/Feature Request')}
|
label={__('Submit a Bug Report/Feature Request')}
|
||||||
icon={icons.REPORT}
|
icon={icons.REPORT}
|
||||||
button="primary"
|
button="primary"
|
||||||
|
|
|
@ -1,6 +1,5 @@
|
||||||
import { connect } from 'react-redux';
|
import { connect } from 'react-redux';
|
||||||
import { doResolveUri, selectBalance } from 'lbry-redux';
|
import { doResolveUri, selectBalance } from 'lbry-redux';
|
||||||
import { doNavigate } from 'redux/actions/navigation';
|
|
||||||
import {
|
import {
|
||||||
selectPublishFormValues,
|
selectPublishFormValues,
|
||||||
selectIsStillEditing,
|
selectIsStillEditing,
|
||||||
|
@ -35,7 +34,6 @@ const perform = dispatch => ({
|
||||||
clearPublish: () => dispatch(doClearPublish()),
|
clearPublish: () => dispatch(doClearPublish()),
|
||||||
resolveUri: uri => dispatch(doResolveUri(uri)),
|
resolveUri: uri => dispatch(doResolveUri(uri)),
|
||||||
publish: params => dispatch(doPublish(params)),
|
publish: params => dispatch(doPublish(params)),
|
||||||
navigate: path => dispatch(doNavigate(path)),
|
|
||||||
prepareEdit: (claim, uri) => dispatch(doPrepareEdit(claim, uri)),
|
prepareEdit: (claim, uri) => dispatch(doPrepareEdit(claim, uri)),
|
||||||
resetThumbnailStatus: () => dispatch(doResetThumbnailStatus()),
|
resetThumbnailStatus: () => dispatch(doResetThumbnailStatus()),
|
||||||
});
|
});
|
||||||
|
|
|
@ -6,7 +6,7 @@ import {
|
||||||
selectUser,
|
selectUser,
|
||||||
doRewardList,
|
doRewardList,
|
||||||
} from 'lbryinc';
|
} from 'lbryinc';
|
||||||
import { doAuthNavigate, doNavigate } from 'redux/actions/navigation';
|
import { navigate } from '@reach/router';
|
||||||
import { selectDaemonSettings } from 'redux/selectors/settings';
|
import { selectDaemonSettings } from 'redux/selectors/settings';
|
||||||
import RewardsPage from './view';
|
import RewardsPage from './view';
|
||||||
|
|
||||||
|
@ -20,9 +20,8 @@ const select = state => ({
|
||||||
|
|
||||||
const perform = dispatch => ({
|
const perform = dispatch => ({
|
||||||
fetchRewards: () => dispatch(doRewardList()),
|
fetchRewards: () => dispatch(doRewardList()),
|
||||||
navigate: path => dispatch(doNavigate(path)),
|
|
||||||
doAuth: () => {
|
doAuth: () => {
|
||||||
dispatch(doAuthNavigate('/rewards'));
|
navigate('/$/auth?redirect=rewards');
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
|
@ -11,7 +11,6 @@ import { rewards as REWARD_TYPES } from 'lbryinc';
|
||||||
|
|
||||||
type Props = {
|
type Props = {
|
||||||
doAuth: () => void,
|
doAuth: () => void,
|
||||||
navigate: string => void,
|
|
||||||
fetching: boolean,
|
fetching: boolean,
|
||||||
rewards: Array<Reward>,
|
rewards: Array<Reward>,
|
||||||
claimed: Array<Reward>,
|
claimed: Array<Reward>,
|
||||||
|
@ -28,7 +27,7 @@ type Props = {
|
||||||
|
|
||||||
class RewardsPage extends PureComponent<Props> {
|
class RewardsPage extends PureComponent<Props> {
|
||||||
renderPageHeader() {
|
renderPageHeader() {
|
||||||
const { doAuth, navigate, user, daemonSettings } = this.props;
|
const { doAuth, user, daemonSettings } = this.props;
|
||||||
|
|
||||||
if (user && !user.is_reward_approved && daemonSettings && daemonSettings.share_usage_data) {
|
if (user && !user.is_reward_approved && daemonSettings && daemonSettings.share_usage_data) {
|
||||||
if (!user.primary_email || !user.has_verified_email || !user.is_identity_verified) {
|
if (!user.primary_email || !user.has_verified_email || !user.is_identity_verified) {
|
||||||
|
@ -68,7 +67,7 @@ class RewardsPage extends PureComponent<Props> {
|
||||||
)}`}
|
)}`}
|
||||||
</p>
|
</p>
|
||||||
<p>
|
<p>
|
||||||
<Button onClick={() => navigate('/discover')} button="primary" label="Return Home" />
|
<Button navigate="/" button="primary" label="Return Home" />
|
||||||
</p>
|
</p>
|
||||||
</section>
|
</section>
|
||||||
);
|
);
|
||||||
|
@ -93,7 +92,7 @@ class RewardsPage extends PureComponent<Props> {
|
||||||
}
|
}
|
||||||
|
|
||||||
renderUnclaimedRewards() {
|
renderUnclaimedRewards() {
|
||||||
const { fetching, rewards, user, daemonSettings, navigate, claimed } = this.props;
|
const { fetching, rewards, user, daemonSettings, claimed } = this.props;
|
||||||
|
|
||||||
if (daemonSettings && !daemonSettings.share_usage_data) {
|
if (daemonSettings && !daemonSettings.share_usage_data) {
|
||||||
return (
|
return (
|
||||||
|
@ -104,7 +103,7 @@ class RewardsPage extends PureComponent<Props> {
|
||||||
{__(
|
{__(
|
||||||
'Rewards are currently disabled for your account. Turn on diagnostic data sharing, in'
|
'Rewards are currently disabled for your account. Turn on diagnostic data sharing, in'
|
||||||
)}{' '}
|
)}{' '}
|
||||||
<Button button="link" onClick={() => navigate('/settings')} label="Settings" />
|
<Button button="link" navigate="/$/settings" label="Settings" />
|
||||||
{__(', in order to re-enable them.')}
|
{__(', in order to re-enable them.')}
|
||||||
</p>
|
</p>
|
||||||
</header>
|
</header>
|
||||||
|
@ -132,8 +131,8 @@ class RewardsPage extends PureComponent<Props> {
|
||||||
<p className="card__content">
|
<p className="card__content">
|
||||||
{claimed && claimed.length
|
{claimed && claimed.length
|
||||||
? __(
|
? __(
|
||||||
"You have claimed all available rewards! We're regularly adding more so be sure to check back later."
|
"You have claimed all available rewards! We're regularly adding more so be sure to check back later."
|
||||||
)
|
)
|
||||||
: __('There are no rewards available at this time, please check back later.')}
|
: __('There are no rewards available at this time, please check back later.')}
|
||||||
</p>
|
</p>
|
||||||
</section>
|
</section>
|
||||||
|
|
|
@ -1,17 +1,14 @@
|
||||||
import { connect } from 'react-redux';
|
import { connect } from 'react-redux';
|
||||||
import { selectIsSearching, makeSelectCurrentParam, doUpdateSearchQuery } from 'lbry-redux';
|
import { doSearch, selectIsSearching } from 'lbry-redux';
|
||||||
import { doNavigate } from 'redux/actions/navigation';
|
|
||||||
import SearchPage from './view';
|
import SearchPage from './view';
|
||||||
|
|
||||||
const select = state => ({
|
const select = state => ({
|
||||||
isSearching: selectIsSearching(state),
|
isSearching: selectIsSearching(state),
|
||||||
query: makeSelectCurrentParam('query')(state),
|
|
||||||
});
|
});
|
||||||
|
|
||||||
const perform = dispatch => ({
|
const perform = {
|
||||||
navigate: path => dispatch(doNavigate(path)),
|
doSearch,
|
||||||
updateSearchQuery: query => dispatch(doUpdateSearchQuery(query)),
|
};
|
||||||
});
|
|
||||||
|
|
||||||
export default connect(
|
export default connect(
|
||||||
select,
|
select,
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
// @flow
|
// @flow
|
||||||
|
import type { UrlLocation } from 'types/location';
|
||||||
import * as ICONS from 'constants/icons';
|
import * as ICONS from 'constants/icons';
|
||||||
import * as React from 'react';
|
import React, { useEffect, Fragment } from 'react';
|
||||||
import { isURIValid, normalizeURI, parseURI } from 'lbry-redux';
|
import { isURIValid, normalizeURI, parseURI } from 'lbry-redux';
|
||||||
import FileTile from 'component/fileTile';
|
import FileTile from 'component/fileTile';
|
||||||
import ChannelTile from 'component/channelTile';
|
import ChannelTile from 'component/channelTile';
|
||||||
|
@ -9,55 +10,88 @@ import Page from 'component/page';
|
||||||
import ToolTip from 'component/common/tooltip';
|
import ToolTip from 'component/common/tooltip';
|
||||||
import Icon from 'component/common/icon';
|
import Icon from 'component/common/icon';
|
||||||
import SearchOptions from 'component/searchOptions';
|
import SearchOptions from 'component/searchOptions';
|
||||||
|
import { Location } from '@reach/router';
|
||||||
|
|
||||||
type Props = {
|
type Props = { doSearch: string => void, location: UrlLocation };
|
||||||
query: ?string,
|
|
||||||
};
|
|
||||||
|
|
||||||
class SearchPage extends React.PureComponent<Props> {
|
export default function SearchPage(props: Props) {
|
||||||
render() {
|
const {
|
||||||
const { query } = this.props;
|
doSearch,
|
||||||
const isValid = isURIValid(query);
|
location: { search },
|
||||||
|
} = props;
|
||||||
|
|
||||||
let uri;
|
const urlParams = new URLSearchParams(location.search);
|
||||||
let isChannel;
|
const urlQuery = urlParams.get('q');
|
||||||
if (isValid) {
|
|
||||||
uri = normalizeURI(query);
|
useEffect(() => {
|
||||||
({ isChannel } = parseURI(uri));
|
if (urlQuery) {
|
||||||
|
doSearch(urlQuery);
|
||||||
}
|
}
|
||||||
|
}, [urlQuery]);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Page noPadding>
|
<Page noPadding>
|
||||||
<section className="search">
|
<Location>
|
||||||
{query && isValid && (
|
{(locationProps: {
|
||||||
<header className="search__header">
|
location: {
|
||||||
<h1 className="search__title">
|
search: string,
|
||||||
{`lbry://${query}`}
|
},
|
||||||
<ToolTip
|
}) => {
|
||||||
icon
|
const { location } = locationProps;
|
||||||
body={__('This is the resolution of a LBRY URL and not controlled by LBRY Inc.')}
|
const urlParams = new URLSearchParams(location.search);
|
||||||
>
|
const query = urlParams.get('q');
|
||||||
<Icon icon={ICONS.HELP} />
|
const isValid = isURIValid(query);
|
||||||
</ToolTip>
|
|
||||||
</h1>
|
let uri;
|
||||||
{isChannel ? (
|
let isChannel;
|
||||||
<ChannelTile size="large" isSearchResult uri={uri} />
|
let label;
|
||||||
) : (
|
if (isValid) {
|
||||||
<FileTile size="large" isSearchResult displayHiddenMessage uri={uri} />
|
uri = normalizeURI(query);
|
||||||
|
({ isChannel } = parseURI(uri));
|
||||||
|
// label = (
|
||||||
|
// <Fragment>
|
||||||
|
// {`lbry://${query}`}
|
||||||
|
// <ToolTip
|
||||||
|
// icon
|
||||||
|
// body={__('This is the resolution of a LBRY URL and not controlled by LBRY Inc.')}
|
||||||
|
// >
|
||||||
|
// <Icon icon={ICONS.HELP} />
|
||||||
|
// </ToolTip>
|
||||||
|
// </Fragment>
|
||||||
|
// );
|
||||||
|
}
|
||||||
|
|
||||||
|
return (
|
||||||
|
<section className="search">
|
||||||
|
{query && (
|
||||||
|
<Fragment>
|
||||||
|
<header className="search__header">
|
||||||
|
{isValid && (
|
||||||
|
<Fragment>
|
||||||
|
<SearchOptions />
|
||||||
|
|
||||||
|
<h1 className="media__uri">{uri}</h1>
|
||||||
|
{isChannel ? (
|
||||||
|
<ChannelTile size="large" isSearchResult uri={uri} />
|
||||||
|
) : (
|
||||||
|
<FileTile size="large" isSearchResult displayHiddenMessage uri={uri} />
|
||||||
|
)}
|
||||||
|
</Fragment>
|
||||||
|
)}
|
||||||
|
</header>
|
||||||
|
|
||||||
|
<div className="search__results-wrapper">
|
||||||
|
<FileListSearch query={query} />
|
||||||
|
<div className="card__content help">
|
||||||
|
{__('These search results are provided by LBRY, Inc.')}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</Fragment>
|
||||||
)}
|
)}
|
||||||
</header>
|
</section>
|
||||||
)}
|
);
|
||||||
|
}}
|
||||||
<div className="search__results-wrapper">
|
</Location>
|
||||||
<SearchOptions />
|
</Page>
|
||||||
|
);
|
||||||
<FileListSearch query={query} />
|
|
||||||
<div className="help">{__('These search results are provided by LBRY, Inc.')}</div>
|
|
||||||
</div>
|
|
||||||
</section>
|
|
||||||
</Page>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
export default SearchPage;
|
|
||||||
|
|
|
@ -5,16 +5,22 @@ import {
|
||||||
makeSelectClaimForUri,
|
makeSelectClaimForUri,
|
||||||
makeSelectIsUriResolving,
|
makeSelectIsUriResolving,
|
||||||
makeSelectTotalPagesForChannel,
|
makeSelectTotalPagesForChannel,
|
||||||
|
buildURI,
|
||||||
} from 'lbry-redux';
|
} from 'lbry-redux';
|
||||||
import { selectBlackListedOutpoints } from 'lbryinc';
|
import { selectBlackListedOutpoints } from 'lbryinc';
|
||||||
import ShowPage from './view';
|
import ShowPage from './view';
|
||||||
|
|
||||||
const select = (state, props) => ({
|
const select = (state, props) => {
|
||||||
claim: makeSelectClaimForUri(props.uri)(state),
|
// claimName and claimId come from the url `lbry.tv/{claimName}/{claimId}"
|
||||||
isResolvingUri: makeSelectIsUriResolving(props.uri)(state),
|
const uri = buildURI({ contentName: props.claimName, claimId: props.claimId });
|
||||||
blackListedOutpoints: selectBlackListedOutpoints(state),
|
return {
|
||||||
totalPages: makeSelectTotalPagesForChannel(props.uri, PAGE_SIZE)(state),
|
claim: makeSelectClaimForUri(uri)(state),
|
||||||
});
|
isResolvingUri: makeSelectIsUriResolving(uri)(state),
|
||||||
|
blackListedOutpoints: selectBlackListedOutpoints(state),
|
||||||
|
totalPages: makeSelectTotalPagesForChannel(uri, PAGE_SIZE)(state),
|
||||||
|
uri: uri,
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
const perform = dispatch => ({
|
const perform = dispatch => ({
|
||||||
resolveUri: uri => dispatch(doResolveUri(uri)),
|
resolveUri: uri => dispatch(doResolveUri(uri)),
|
||||||
|
|
|
@ -1,4 +1,5 @@
|
||||||
// @flow
|
// @flow
|
||||||
|
import type { UrlLocation } from 'types/location';
|
||||||
import React from 'react';
|
import React from 'react';
|
||||||
import BusyIndicator from 'component/common/busy-indicator';
|
import BusyIndicator from 'component/common/busy-indicator';
|
||||||
import ChannelPage from 'page/channel';
|
import ChannelPage from 'page/channel';
|
||||||
|
@ -13,6 +14,7 @@ type Props = {
|
||||||
uri: string,
|
uri: string,
|
||||||
claim: Claim,
|
claim: Claim,
|
||||||
totalPages: number,
|
totalPages: number,
|
||||||
|
location: UrlLocation,
|
||||||
blackListedOutpoints: Array<{
|
blackListedOutpoints: Array<{
|
||||||
txid: string,
|
txid: string,
|
||||||
nout: number,
|
nout: number,
|
||||||
|
@ -38,8 +40,7 @@ class ShowPage extends React.PureComponent<Props> {
|
||||||
}
|
}
|
||||||
|
|
||||||
render() {
|
render() {
|
||||||
const { claim, isResolvingUri, uri, blackListedOutpoints } = this.props;
|
const { claim, isResolvingUri, uri, blackListedOutpoints, location } = this.props;
|
||||||
|
|
||||||
let innerContent = '';
|
let innerContent = '';
|
||||||
|
|
||||||
if (!claim || (claim && !claim.name)) {
|
if (!claim || (claim && !claim.name)) {
|
||||||
|
@ -58,7 +59,7 @@ class ShowPage extends React.PureComponent<Props> {
|
||||||
</Page>
|
</Page>
|
||||||
);
|
);
|
||||||
} else if (claim.name.length && claim.name[0] === '@') {
|
} else if (claim.name.length && claim.name[0] === '@') {
|
||||||
innerContent = <ChannelPage uri={uri} />;
|
innerContent = <ChannelPage uri={uri} location={location} />;
|
||||||
} else if (claim && blackListedOutpoints) {
|
} else if (claim && blackListedOutpoints) {
|
||||||
let isClaimBlackListed = false;
|
let isClaimBlackListed = false;
|
||||||
|
|
||||||
|
@ -89,7 +90,7 @@ class ShowPage extends React.PureComponent<Props> {
|
||||||
</Page>
|
</Page>
|
||||||
);
|
);
|
||||||
} else {
|
} else {
|
||||||
innerContent = <FilePage uri={uri} />;
|
innerContent = <FilePage uri={uri} location={location} />;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -13,6 +13,7 @@ import SuggestedSubscriptions from 'component/subscribeSuggested';
|
||||||
import MarkAsRead from 'component/subscribeMarkAsRead';
|
import MarkAsRead from 'component/subscribeMarkAsRead';
|
||||||
import Tooltip from 'component/common/tooltip';
|
import Tooltip from 'component/common/tooltip';
|
||||||
import Yrbl from 'component/yrbl';
|
import Yrbl from 'component/yrbl';
|
||||||
|
import { formatLbryUriForWeb } from 'util/uri';
|
||||||
|
|
||||||
type Props = {
|
type Props = {
|
||||||
viewMode: ViewMode,
|
viewMode: ViewMode,
|
||||||
|
@ -109,12 +110,7 @@ export default (props: Props) => {
|
||||||
return (
|
return (
|
||||||
<span>
|
<span>
|
||||||
<h2 className="card__title card__title--flex">
|
<h2 className="card__title card__title--flex">
|
||||||
<Button
|
<Button button="link" navigate={channel} label={claimName} />
|
||||||
button="link"
|
|
||||||
navigate="/show"
|
|
||||||
navigateParams={{ uri: channel, page: 1 }}
|
|
||||||
label={claimName}
|
|
||||||
/>
|
|
||||||
<MarkAsRead channel={channel} />
|
<MarkAsRead channel={channel} />
|
||||||
</h2>
|
</h2>
|
||||||
|
|
||||||
|
|
|
@ -9,7 +9,7 @@ class UserHistoryPage extends React.PureComponent<Props> {
|
||||||
render() {
|
render() {
|
||||||
return (
|
return (
|
||||||
<Page>
|
<Page>
|
||||||
<UserHistory />
|
<UserHistory {...this.props} />
|
||||||
</Page>
|
</Page>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
|
@ -6,6 +6,7 @@ import TransactionListRecent from 'component/transactionListRecent';
|
||||||
import WalletAddress from 'component/walletAddress';
|
import WalletAddress from 'component/walletAddress';
|
||||||
import Page from 'component/page';
|
import Page from 'component/page';
|
||||||
import UnsupportedOnWeb from 'component/common/unsupported-on-web';
|
import UnsupportedOnWeb from 'component/common/unsupported-on-web';
|
||||||
|
import WalletSend from 'component/walletSend';
|
||||||
|
|
||||||
const WalletPage = () => (
|
const WalletPage = () => (
|
||||||
<Page>
|
<Page>
|
||||||
|
@ -15,6 +16,7 @@ const WalletPage = () => (
|
||||||
<WalletBalance />
|
<WalletBalance />
|
||||||
<RewardSummary />
|
<RewardSummary />
|
||||||
</div>
|
</div>
|
||||||
|
<WalletSend />
|
||||||
<WalletAddress />
|
<WalletAddress />
|
||||||
<TransactionListRecent />
|
<TransactionListRecent />
|
||||||
</div>
|
</div>
|
||||||
|
|
|
@ -317,6 +317,7 @@ export function doDaemonReady() {
|
||||||
dispatch({ type: ACTIONS.DAEMON_READY });
|
dispatch({ type: ACTIONS.DAEMON_READY });
|
||||||
dispatch(doFetchDaemonSettings());
|
dispatch(doFetchDaemonSettings());
|
||||||
dispatch(doBalanceSubscribe());
|
dispatch(doBalanceSubscribe());
|
||||||
|
|
||||||
// @if TARGET='app'
|
// @if TARGET='app'
|
||||||
dispatch(doFetchFileInfosAndPublishedClaims());
|
dispatch(doFetchFileInfosAndPublishedClaims());
|
||||||
if (!selectIsUpgradeSkipped(state)) {
|
if (!selectIsUpgradeSkipped(state)) {
|
||||||
|
|
|
@ -7,7 +7,7 @@ import * as MODALS from 'constants/modal_types';
|
||||||
import { ipcRenderer } from 'electron';
|
import { ipcRenderer } from 'electron';
|
||||||
// @endif
|
// @endif
|
||||||
import { doOpenModal } from 'redux/actions/app';
|
import { doOpenModal } from 'redux/actions/app';
|
||||||
import { doNavigate } from 'redux/actions/navigation';
|
import { navigate } from '@reach/router';
|
||||||
import { setSubscriptionLatest, doUpdateUnreadSubscriptions } from 'redux/actions/subscriptions';
|
import { setSubscriptionLatest, doUpdateUnreadSubscriptions } from 'redux/actions/subscriptions';
|
||||||
import { makeSelectUnreadByChannel } from 'redux/selectors/subscriptions';
|
import { makeSelectUnreadByChannel } from 'redux/selectors/subscriptions';
|
||||||
import {
|
import {
|
||||||
|
@ -24,10 +24,11 @@ import {
|
||||||
parseURI,
|
parseURI,
|
||||||
creditsToString,
|
creditsToString,
|
||||||
doError,
|
doError,
|
||||||
|
makeSelectCostInfoForUri,
|
||||||
} from 'lbry-redux';
|
} from 'lbry-redux';
|
||||||
import { makeSelectCostInfoForUri } from 'lbryinc';
|
|
||||||
import { makeSelectClientSetting, selectosNotificationsEnabled } from 'redux/selectors/settings';
|
import { makeSelectClientSetting, selectosNotificationsEnabled } from 'redux/selectors/settings';
|
||||||
import analytics from 'analytics';
|
import analytics from 'analytics';
|
||||||
|
import { formatLbryUriForWeb } from 'util/uri';
|
||||||
|
|
||||||
const DOWNLOAD_POLL_INTERVAL = 250;
|
const DOWNLOAD_POLL_INTERVAL = 250;
|
||||||
|
|
||||||
|
@ -82,11 +83,7 @@ export function doUpdateLoadStatus(uri: string, outpoint: string) {
|
||||||
silent: false,
|
silent: false,
|
||||||
});
|
});
|
||||||
notif.onclick = () => {
|
notif.onclick = () => {
|
||||||
dispatch(
|
navigate(formatLbryUriForWeb(uri));
|
||||||
doNavigate('/show', {
|
|
||||||
uri,
|
|
||||||
})
|
|
||||||
);
|
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -10,7 +10,6 @@ import {
|
||||||
selectFileInfosByOutpoint,
|
selectFileInfosByOutpoint,
|
||||||
} from 'lbry-redux';
|
} from 'lbry-redux';
|
||||||
import { doHideModal } from 'redux/actions/app';
|
import { doHideModal } from 'redux/actions/app';
|
||||||
import { doHistoryBack } from 'redux/actions/navigation';
|
|
||||||
|
|
||||||
export function doOpenFileInFolder(path) {
|
export function doOpenFileInFolder(path) {
|
||||||
return () => {
|
return () => {
|
||||||
|
@ -63,7 +62,6 @@ export function doDeleteFileAndGoBack(fileInfo, deleteFromComputer, abandonClaim
|
||||||
return dispatch => {
|
return dispatch => {
|
||||||
const actions = [];
|
const actions = [];
|
||||||
actions.push(doHideModal());
|
actions.push(doHideModal());
|
||||||
actions.push(doHistoryBack());
|
|
||||||
actions.push(doDeleteFile(fileInfo, deleteFromComputer, abandonClaim));
|
actions.push(doDeleteFile(fileInfo, deleteFromComputer, abandonClaim));
|
||||||
dispatch(batchActions(...actions));
|
dispatch(batchActions(...actions));
|
||||||
};
|
};
|
||||||
|
|
|
@ -1,74 +0,0 @@
|
||||||
import { ACTIONS, selectHistoryIndex, selectHistoryStack } from 'lbry-redux';
|
|
||||||
import { toQueryString } from 'util/query-params';
|
|
||||||
import analytics from 'analytics';
|
|
||||||
|
|
||||||
export function doNavigate(path, params = {}, options = {}) {
|
|
||||||
return dispatch => {
|
|
||||||
if (!path) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// ensure uri always has "lbry://" prefix
|
|
||||||
const navigationParams = params;
|
|
||||||
if (path === '/show') {
|
|
||||||
if (navigationParams.uri && !navigationParams.uri.startsWith('lbry://')) {
|
|
||||||
navigationParams.uri = `lbry://${navigationParams.uri}`;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
let url = path;
|
|
||||||
if (params && Object.values(params).length) {
|
|
||||||
url += `?${toQueryString(params)}`;
|
|
||||||
}
|
|
||||||
|
|
||||||
analytics.track('NAVIGATION', { destination: url });
|
|
||||||
|
|
||||||
const { scrollY } = options;
|
|
||||||
|
|
||||||
dispatch({
|
|
||||||
type: ACTIONS.HISTORY_NAVIGATE,
|
|
||||||
data: { url, index: options.index, scrollY },
|
|
||||||
});
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
export function doAuthNavigate(pathAfterAuth = null, params = {}) {
|
|
||||||
return dispatch => {
|
|
||||||
if (pathAfterAuth) {
|
|
||||||
dispatch({
|
|
||||||
type: ACTIONS.CHANGE_AFTER_AUTH_PATH,
|
|
||||||
data: {
|
|
||||||
path: `${pathAfterAuth}?${toQueryString(params)}`,
|
|
||||||
},
|
|
||||||
});
|
|
||||||
}
|
|
||||||
dispatch(doNavigate('/auth'));
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
export function doHistoryTraverse(dispatch, state, modifier) {
|
|
||||||
const stack = selectHistoryStack(state);
|
|
||||||
const index = selectHistoryIndex(state) + modifier;
|
|
||||||
|
|
||||||
if (index >= 0 && index < stack.length) {
|
|
||||||
const historyItem = stack[index];
|
|
||||||
dispatch(doNavigate(historyItem.path, {}, { scrollY: historyItem.scrollY, index }));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
export function doHistoryBack() {
|
|
||||||
return (dispatch, getState) => doHistoryTraverse(dispatch, getState(), -1);
|
|
||||||
}
|
|
||||||
|
|
||||||
export function doHistoryForward() {
|
|
||||||
return (dispatch, getState) => doHistoryTraverse(dispatch, getState(), 1);
|
|
||||||
}
|
|
||||||
|
|
||||||
export function doRecordScroll(scroll) {
|
|
||||||
return dispatch => {
|
|
||||||
dispatch({
|
|
||||||
type: ACTIONS.WINDOW_SCROLLED,
|
|
||||||
data: { scrollY: scroll },
|
|
||||||
});
|
|
||||||
};
|
|
||||||
}
|
|
|
@ -21,8 +21,9 @@ import {
|
||||||
} from 'lbry-redux';
|
} from 'lbry-redux';
|
||||||
import { doOpenModal } from 'redux/actions/app';
|
import { doOpenModal } from 'redux/actions/app';
|
||||||
import { selectosNotificationsEnabled } from 'redux/selectors/settings';
|
import { selectosNotificationsEnabled } from 'redux/selectors/settings';
|
||||||
import { doNavigate } from 'redux/actions/navigation';
|
import { navigate } from '@reach/router';
|
||||||
import analytics from 'analytics';
|
import analytics from 'analytics';
|
||||||
|
import { formatLbryUriForWeb } from 'util/uri';
|
||||||
// @if TARGET='app'
|
// @if TARGET='app'
|
||||||
import fs from 'fs';
|
import fs from 'fs';
|
||||||
import path from 'path';
|
import path from 'path';
|
||||||
|
@ -127,12 +128,12 @@ export const doUploadThumbnail = (filePath: string, nsfw: boolean) => (dispatch:
|
||||||
.then(json =>
|
.then(json =>
|
||||||
json.success
|
json.success
|
||||||
? dispatch({
|
? dispatch({
|
||||||
type: ACTIONS.UPDATE_PUBLISH_FORM,
|
type: ACTIONS.UPDATE_PUBLISH_FORM,
|
||||||
data: {
|
data: {
|
||||||
uploadThumbnailStatus: THUMBNAIL_STATUSES.COMPLETE,
|
uploadThumbnailStatus: THUMBNAIL_STATUSES.COMPLETE,
|
||||||
thumbnail: `${json.data.url}${fileExt}`,
|
thumbnail: `${json.data.url}${fileExt}`,
|
||||||
},
|
},
|
||||||
})
|
})
|
||||||
: uploadError(json.message)
|
: uploadError(json.message)
|
||||||
)
|
)
|
||||||
.catch(err => uploadError(err.message));
|
.catch(err => uploadError(err.message));
|
||||||
|
@ -327,11 +328,7 @@ export const doCheckPendingPublishes = () => (dispatch: Dispatch, getState: GetS
|
||||||
silent: false,
|
silent: false,
|
||||||
});
|
});
|
||||||
notif.onclick = () => {
|
notif.onclick = () => {
|
||||||
dispatch(
|
navigate(formatLbryUriForWeb(claim.permanent_url));
|
||||||
doNavigate('/show', {
|
|
||||||
uri: claim.permanent_url,
|
|
||||||
})
|
|
||||||
);
|
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -100,21 +100,6 @@ export const selectDaemonVersionMatched = createSelector(
|
||||||
state => state.daemonVersionMatched
|
state => state.daemonVersionMatched
|
||||||
);
|
);
|
||||||
|
|
||||||
export const selectSnackBar = createSelector(
|
|
||||||
selectState,
|
|
||||||
state => state.snackBar || {}
|
|
||||||
);
|
|
||||||
|
|
||||||
export const selectSnackBarSnacks = createSelector(
|
|
||||||
selectSnackBar,
|
|
||||||
snackBar => snackBar.snacks || []
|
|
||||||
);
|
|
||||||
|
|
||||||
export const selectBadgeNumber = createSelector(
|
|
||||||
selectState,
|
|
||||||
state => state.badgeNumber
|
|
||||||
);
|
|
||||||
|
|
||||||
export const selectCurrentLanguage = createSelector(
|
export const selectCurrentLanguage = createSelector(
|
||||||
selectState,
|
selectState,
|
||||||
() => i18n.getLocale() || 'en'
|
() => i18n.getLocale() || 'en'
|
||||||
|
@ -130,147 +115,6 @@ export const selectUpgradeTimer = createSelector(
|
||||||
state => state.checkUpgradeTimer
|
state => state.checkUpgradeTimer
|
||||||
);
|
);
|
||||||
|
|
||||||
export const selectNavLinks = createSelector(
|
|
||||||
selectCurrentPage,
|
|
||||||
selectHistoryStack,
|
|
||||||
makeSelectClientSetting(SETTINGS.FIRST_RUN_COMPLETED),
|
|
||||||
makeSelectClientSetting(SETTINGS.INVITE_ACKNOWLEDGED),
|
|
||||||
(currentPage, historyStack, firstRunCompleted, inviteAcknowledged) => {
|
|
||||||
// Determine if any links should show a tooltip for a guided tour
|
|
||||||
// It will only show one at a time, in the order they are set.
|
|
||||||
const guidedTourItem = [
|
|
||||||
// @if TARGET='app'
|
|
||||||
{
|
|
||||||
page: PAGES.INVITE,
|
|
||||||
hasBeenCompleted: inviteAcknowledged,
|
|
||||||
guide: 'Check this out!',
|
|
||||||
},
|
|
||||||
// @endif
|
|
||||||
// Add more items below for tooltip guides that will happen after a user has completed the invite guide
|
|
||||||
].filter(({ hasBeenCompleted }) => !hasBeenCompleted)[0];
|
|
||||||
|
|
||||||
const isWalletPage = page =>
|
|
||||||
page === PAGES.WALLET ||
|
|
||||||
page === PAGES.SEND ||
|
|
||||||
page === PAGES.GET_CREDITS ||
|
|
||||||
page === PAGES.HISTORY ||
|
|
||||||
page === PAGES.BACKUP;
|
|
||||||
|
|
||||||
const isCurrentlyWalletPage = isWalletPage(currentPage);
|
|
||||||
const previousStack = historyStack.slice().reverse();
|
|
||||||
|
|
||||||
const getPreviousSubLinkPath = checkIfValidPage => {
|
|
||||||
for (let i = 0; i < previousStack.length; i += 1) {
|
|
||||||
const currentStackItem = previousStack[i];
|
|
||||||
|
|
||||||
// Trim off the "/" from the path
|
|
||||||
const pageInStack = currentStackItem.path.slice(1);
|
|
||||||
if (checkIfValidPage(pageInStack)) {
|
|
||||||
return currentStackItem.path;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return undefined;
|
|
||||||
};
|
|
||||||
|
|
||||||
// Gets the last active sublink in a section
|
|
||||||
const getActiveSublink = category => {
|
|
||||||
if (category === PAGES.WALLET) {
|
|
||||||
const previousPath = getPreviousSubLinkPath(isWalletPage);
|
|
||||||
return previousPath || `/${PAGES.WALLET}`;
|
|
||||||
}
|
|
||||||
|
|
||||||
return undefined;
|
|
||||||
};
|
|
||||||
|
|
||||||
// Is this path the first unacknowledged item in the guided tour list
|
|
||||||
const getGuideIfNecessary = page => {
|
|
||||||
if (!firstRunCompleted) {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
return guidedTourItem && guidedTourItem.page === page ? guidedTourItem.guide : null;
|
|
||||||
};
|
|
||||||
|
|
||||||
const buildLink = (label, page) => ({
|
|
||||||
label,
|
|
||||||
path: `/${page}`,
|
|
||||||
active: currentPage === page,
|
|
||||||
guide: getGuideIfNecessary(page),
|
|
||||||
});
|
|
||||||
|
|
||||||
const walletSubLinks = [
|
|
||||||
{
|
|
||||||
...buildLink('Overview', PAGES.WALLET),
|
|
||||||
},
|
|
||||||
{
|
|
||||||
...buildLink('Send & Receive', PAGES.SEND),
|
|
||||||
},
|
|
||||||
{
|
|
||||||
...buildLink('Transactions', PAGES.HISTORY),
|
|
||||||
},
|
|
||||||
{
|
|
||||||
...buildLink('Get Credits', PAGES.GET_CREDITS),
|
|
||||||
},
|
|
||||||
{
|
|
||||||
...buildLink('Backup', PAGES.BACKUP),
|
|
||||||
},
|
|
||||||
];
|
|
||||||
|
|
||||||
const navLinks = {
|
|
||||||
primary: [
|
|
||||||
{
|
|
||||||
...buildLink('Explore', PAGES.DISCOVER),
|
|
||||||
icon: ICONS.HOME,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
...buildLink('Subscriptions', PAGES.SUBSCRIPTIONS),
|
|
||||||
icon: ICONS.SUBSCRIPTION,
|
|
||||||
},
|
|
||||||
],
|
|
||||||
secondary: [
|
|
||||||
{
|
|
||||||
label: 'Wallet',
|
|
||||||
icon: ICONS.WALLET,
|
|
||||||
subLinks: walletSubLinks,
|
|
||||||
path: isCurrentlyWalletPage ? `/${PAGES.WALLET}` : getActiveSublink(PAGES.WALLET),
|
|
||||||
active: isWalletPage(currentPage),
|
|
||||||
},
|
|
||||||
{
|
|
||||||
...buildLink('Invite', PAGES.INVITE),
|
|
||||||
icon: ICONS.INVITE,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
...buildLink('Rewards', PAGES.REWARDS),
|
|
||||||
// This probably shouldn't use the "FEATURED" icon, but not sure what else to use
|
|
||||||
icon: ICONS.FEATURED,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
...buildLink('Downloads', PAGES.DOWNLOADED),
|
|
||||||
icon: ICONS.LOCAL,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
...buildLink('Publishes', PAGES.PUBLISHED),
|
|
||||||
icon: ICONS.PUBLISHED,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
...buildLink('History', PAGES.USER_HISTORY),
|
|
||||||
icon: ICONS.HISTORY,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
...buildLink('Settings', PAGES.SETTINGS),
|
|
||||||
icon: ICONS.SETTINGS,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
...buildLink('Help', PAGES.HELP),
|
|
||||||
icon: ICONS.HELP,
|
|
||||||
},
|
|
||||||
],
|
|
||||||
};
|
|
||||||
|
|
||||||
return navLinks;
|
|
||||||
}
|
|
||||||
);
|
|
||||||
|
|
||||||
export const selectModal = createSelector(
|
export const selectModal = createSelector(
|
||||||
selectState,
|
selectState,
|
||||||
state => {
|
state => {
|
||||||
|
|
|
@ -3,7 +3,7 @@ import { createSelector } from 'reselect';
|
||||||
import {
|
import {
|
||||||
makeSelectClaimForUri,
|
makeSelectClaimForUri,
|
||||||
selectClaimsByUri,
|
selectClaimsByUri,
|
||||||
makeSelectClaimsInChannelForCurrentPage,
|
makeSelectClaimsInChannelForCurrentPageState,
|
||||||
} from 'lbry-redux';
|
} from 'lbry-redux';
|
||||||
import { HISTORY_ITEMS_PER_PAGE } from 'constants/content';
|
import { HISTORY_ITEMS_PER_PAGE } from 'constants/content';
|
||||||
|
|
||||||
|
@ -68,7 +68,7 @@ export const makeSelectHistoryForUri = (uri: string) =>
|
||||||
|
|
||||||
export const makeSelectCategoryListUris = (uris: ?Array<string>, channel: string) =>
|
export const makeSelectCategoryListUris = (uris: ?Array<string>, channel: string) =>
|
||||||
createSelector(
|
createSelector(
|
||||||
makeSelectClaimsInChannelForCurrentPage(channel),
|
makeSelectClaimsInChannelForCurrentPageState(channel),
|
||||||
channelClaims => {
|
channelClaims => {
|
||||||
if (uris) return uris;
|
if (uris) return uris;
|
||||||
|
|
||||||
|
|
|
@ -2,6 +2,7 @@
|
||||||
|
|
||||||
.button {
|
.button {
|
||||||
border-radius: 0;
|
border-radius: 0;
|
||||||
|
font-size: 1em;
|
||||||
|
|
||||||
svg {
|
svg {
|
||||||
stroke-width: 1.9;
|
stroke-width: 1.9;
|
||||||
|
|
|
@ -27,7 +27,12 @@
|
||||||
// at smaller screen widths
|
// at smaller screen widths
|
||||||
|
|
||||||
@media (min-width: 601px) {
|
@media (min-width: 601px) {
|
||||||
|
/* @if TARGET='app' */
|
||||||
width: 250px;
|
width: 250px;
|
||||||
|
/* @endif */
|
||||||
|
/* @if TARGET='web' */
|
||||||
|
width: 170px;
|
||||||
|
/* @endif */
|
||||||
}
|
}
|
||||||
|
|
||||||
@media (max-width: 600px) {
|
@media (max-width: 600px) {
|
||||||
|
@ -38,9 +43,9 @@
|
||||||
|
|
||||||
.header__navigation-item {
|
.header__navigation-item {
|
||||||
height: var(--header-height);
|
height: var(--header-height);
|
||||||
background-position: center;
|
display: flex;
|
||||||
background-repeat: no-repeat;
|
justify-content: center;
|
||||||
background-size: 50%;
|
align-items: center;
|
||||||
|
|
||||||
&:not(:disabled):hover {
|
&:not(:disabled):hover {
|
||||||
background-color: $lbry-gray-1;
|
background-color: $lbry-gray-1;
|
||||||
|
@ -53,68 +58,49 @@
|
||||||
&:disabled {
|
&:disabled {
|
||||||
opacity: 0.3;
|
opacity: 0.3;
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
.header__navigation-item--back {
|
.button__content {
|
||||||
html[data-mode='dark'] & {
|
line-height: var(--header-height);
|
||||||
svg {
|
overflow: hidden;
|
||||||
stroke: $lbry-white;
|
text-align: center;
|
||||||
}
|
text-overflow: ellipsis;
|
||||||
|
width: 100%;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.header__navigation-item--forward {
|
|
||||||
html[data-mode='dark'] & {
|
|
||||||
svg {
|
|
||||||
stroke: $lbry-white;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.header__navigation-item--home {
|
|
||||||
html[data-mode='dark'] & {
|
|
||||||
svg {
|
|
||||||
stroke: $lbry-white;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.header__navigation-item--menu {
|
|
||||||
html[data-mode='dark'] & {
|
|
||||||
svg {
|
|
||||||
stroke: $lbry-white;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// This menu button does not need to be seen
|
|
||||||
// at larger screen widths
|
|
||||||
|
|
||||||
@media (min-width: 601px) {
|
|
||||||
display: none;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
.header__navigation-item--back,
|
.header__navigation-item--back,
|
||||||
.header__navigation-item--forward,
|
.header__navigation-item--forward,
|
||||||
.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 {
|
||||||
|
&:only-child {
|
||||||
|
// Header icons are a little different because they are larger
|
||||||
|
top: 0.25rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
html[data-mode='dark'] & {
|
||||||
|
stroke: $lbry-white;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Currently not used
|
.header__navigation-item--lbry {
|
||||||
// .header__navigation-item--publish,
|
flex: 1;
|
||||||
// .header__navigation-item--wallet {
|
font-weight: 800;
|
||||||
// // Publish and Wallet links are collapsed
|
font-size: 1.2rem;
|
||||||
// // into a menu at smaller screen widths
|
margin-left: -1.25rem; // Needed because the lbry icon overflows it's parent so the centering is off
|
||||||
//
|
|
||||||
// @media (max-width: 600px) {
|
svg {
|
||||||
// display: none;
|
overflow: visible;
|
||||||
// }
|
color: $lbry-white;
|
||||||
// }
|
opacity: 1;
|
||||||
|
top: -0.2rem;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Publish button
|
// Publish button
|
||||||
.header__navigation-item--right-action {
|
.header__navigation-item--right-action {
|
||||||
display: flex;
|
|
||||||
justify-content: center;
|
|
||||||
position: relative;
|
position: relative;
|
||||||
|
|
||||||
.button__content {
|
.button__content {
|
||||||
|
@ -149,12 +135,24 @@
|
||||||
html[data-mode='dark'] & {
|
html[data-mode='dark'] & {
|
||||||
border-color: $lbry-gray-5;
|
border-color: $lbry-gray-5;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
.button__content {
|
.header__navigation-item--menu {
|
||||||
line-height: var(--header-height);
|
@media (min-width: 601px) {
|
||||||
overflow: hidden;
|
display: none;
|
||||||
text-align: center;
|
}
|
||||||
text-overflow: ellipsis;
|
}
|
||||||
width: 100%;
|
|
||||||
|
// Hide links that will live in the menu bar
|
||||||
|
@media (max-width: 601px) {
|
||||||
|
.header__navigation-item--back,
|
||||||
|
.header__navigation-item--forward,
|
||||||
|
.header__navigation-item--home,
|
||||||
|
.header__navigation-item--right-action {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
.header__navigation:first-child {
|
||||||
|
display: none;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -139,6 +139,12 @@
|
||||||
margin-right: var(--spacing-vertical-small);
|
margin-right: var(--spacing-vertical-small);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.media__uri {
|
||||||
|
font-size: 1.1rem;
|
||||||
|
padding-bottom: 5px;
|
||||||
|
opacity: 0.6;
|
||||||
|
}
|
||||||
|
|
||||||
// M E D I A
|
// M E D I A
|
||||||
// A C T I O N S
|
// A C T I O N S
|
||||||
|
|
||||||
|
@ -508,21 +514,19 @@
|
||||||
font-size: 2rem;
|
font-size: 2rem;
|
||||||
}
|
}
|
||||||
|
|
||||||
@media (max-width: 600px) {
|
|
||||||
font-size: 1.75rem;
|
|
||||||
}
|
|
||||||
|
|
||||||
.channel-info__actions__group {
|
.channel-info__actions__group {
|
||||||
button:first-of-type {
|
.button {
|
||||||
font-size: 2rem;
|
&:first-child {
|
||||||
|
font-size: 2rem;
|
||||||
|
|
||||||
.button__label {
|
.button__label {
|
||||||
margin: 0;
|
margin: 0;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
button:last-of-type {
|
&:last-child {
|
||||||
font-weight: normal;
|
font-weight: normal;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -52,6 +52,11 @@
|
||||||
position: relative;
|
position: relative;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.navigation__links--bottom {
|
||||||
|
position: absolute;
|
||||||
|
bottom: var(--spacing-vertical-large);
|
||||||
|
}
|
||||||
|
|
||||||
.navigation__link {
|
.navigation__link {
|
||||||
display: block;
|
display: block;
|
||||||
line-height: 1.75;
|
line-height: 1.75;
|
||||||
|
@ -102,7 +107,7 @@
|
||||||
|
|
||||||
.navigation__link--title {
|
.navigation__link--title {
|
||||||
margin-bottom: var(--spacing-vertical-small);
|
margin-bottom: var(--spacing-vertical-small);
|
||||||
padding-top: var(--spacing-vertical-medium);
|
padding-top: var(--spacing-vertical-large);
|
||||||
|
|
||||||
color: $lbry-gray-5;
|
color: $lbry-gray-5;
|
||||||
cursor: default;
|
cursor: default;
|
||||||
|
|
|
@ -53,6 +53,7 @@
|
||||||
|
|
||||||
.search__options-wrapper {
|
.search__options-wrapper {
|
||||||
font-size: 1.25em;
|
font-size: 1.25em;
|
||||||
|
padding-bottom: var(--spacing-vertical-large);
|
||||||
}
|
}
|
||||||
|
|
||||||
.search__options {
|
.search__options {
|
||||||
|
|
|
@ -8,7 +8,7 @@
|
||||||
}
|
}
|
||||||
|
|
||||||
.yrbl {
|
.yrbl {
|
||||||
height: 300px;
|
height: 20rem;
|
||||||
margin-right: var(--spacing-vertical-large);
|
margin-right: var(--spacing-vertical-large);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -127,7 +127,7 @@ code {
|
||||||
}
|
}
|
||||||
|
|
||||||
.help {
|
.help {
|
||||||
font-size: 0.9em;
|
font-size: 1rem;
|
||||||
background-color: rgba($lbry-blue-1, 0.1);
|
background-color: rgba($lbry-blue-1, 0.1);
|
||||||
color: $lbry-gray-5;
|
color: $lbry-gray-5;
|
||||||
display: block;
|
display: block;
|
||||||
|
|
|
@ -39,7 +39,7 @@ $large-breakpoint: 1921px;
|
||||||
--button-height: 36px;
|
--button-height: 36px;
|
||||||
|
|
||||||
// Header
|
// Header
|
||||||
--header-height: 3.25rem; // 60px;
|
--header-height: 3.5rem;
|
||||||
|
|
||||||
// Header -> search
|
// Header -> search
|
||||||
--search-modal-input-height: 70px;
|
--search-modal-input-height: 70px;
|
||||||
|
|
Some files were not shown because too many files have changed in this diff Show more
Loading…
Reference in a new issue
This is the other big file. No longer bringing in the nav links from redux. Will add the tutorial back in a future PR.