commit
c07ba58d42
45 changed files with 279 additions and 230 deletions
|
@ -19,7 +19,8 @@
|
||||||
"__": true,
|
"__": true,
|
||||||
"__n": true,
|
"__n": true,
|
||||||
"app": true,
|
"app": true,
|
||||||
"IS_WEB": true
|
"IS_WEB": true,
|
||||||
|
"WEBPACK_PORT": true
|
||||||
},
|
},
|
||||||
"rules": {
|
"rules": {
|
||||||
"comma-dangle": ["error", "always-multiline"],
|
"comma-dangle": ["error", "always-multiline"],
|
||||||
|
|
2
flow-typed/publish.js
vendored
2
flow-typed/publish.js
vendored
|
@ -4,7 +4,7 @@ declare type UpdatePublishFormData = {
|
||||||
filePath?: string,
|
filePath?: string,
|
||||||
contentIsFree?: boolean,
|
contentIsFree?: boolean,
|
||||||
fee?: {
|
fee?: {
|
||||||
amount: number,
|
amount: string,
|
||||||
currency: string,
|
currency: string,
|
||||||
},
|
},
|
||||||
title?: string,
|
title?: string,
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
{
|
{
|
||||||
"name": "LBRY",
|
"name": "LBRY",
|
||||||
"version": "0.32.0-rc.1",
|
"version": "0.32.0-rc.6",
|
||||||
"description": "A browser for the LBRY network, a digital marketplace controlled by its users.",
|
"description": "A browser for the LBRY network, a digital marketplace controlled by its users.",
|
||||||
"keywords": [
|
"keywords": [
|
||||||
"lbry"
|
"lbry"
|
||||||
|
@ -26,7 +26,7 @@
|
||||||
"dev": "yarn dev:electron",
|
"dev": "yarn dev:electron",
|
||||||
"dev:electron": "cross-env NODE_ENV=development node ./src/platforms/electron/devServer.js",
|
"dev:electron": "cross-env NODE_ENV=development node ./src/platforms/electron/devServer.js",
|
||||||
"dev:web": "cross-env NODE_ENV=development webpack-dev-server --open --hot --progress --config webpack.web.config.js",
|
"dev:web": "cross-env NODE_ENV=development webpack-dev-server --open --hot --progress --config webpack.web.config.js",
|
||||||
"dev:internal-apis": "LBRY_API_URL='http://localhost:9090' yarn dev:electron",
|
"dev:internal-apis": "LBRY_API_URL='http://localhost:8080' yarn dev:electron",
|
||||||
"run:web": "cross-env NODE_ENV=production yarn compile:web && node ./dist/web/server.js",
|
"run:web": "cross-env NODE_ENV=production yarn compile:web && node ./dist/web/server.js",
|
||||||
"pack": "electron-builder --dir",
|
"pack": "electron-builder --dir",
|
||||||
"dist": "electron-builder",
|
"dist": "electron-builder",
|
||||||
|
@ -117,7 +117,7 @@
|
||||||
"jsmediatags": "^3.8.1",
|
"jsmediatags": "^3.8.1",
|
||||||
"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#c8126ab21792d7a85e1123a2363af285a0263654",
|
"lbry-redux": "lbryio/lbry-redux#02f6918238110726c0b3b4248c61a84ac0b969e3",
|
||||||
"lbryinc": "lbryio/lbryinc#43d382d9b74d396a581a74d87e4c53105e04f845",
|
"lbryinc": "lbryio/lbryinc#43d382d9b74d396a581a74d87e4c53105e04f845",
|
||||||
"lint-staged": "^7.0.2",
|
"lint-staged": "^7.0.2",
|
||||||
"localforage": "^1.7.1",
|
"localforage": "^1.7.1",
|
||||||
|
@ -151,7 +151,6 @@
|
||||||
"react-router-dom": "^5.0.0",
|
"react-router-dom": "^5.0.0",
|
||||||
"react-simplemde-editor": "^4.0.0",
|
"react-simplemde-editor": "^4.0.0",
|
||||||
"react-toggle": "^4.0.2",
|
"react-toggle": "^4.0.2",
|
||||||
"react-virtualized": "^9.21.0",
|
|
||||||
"redux": "^3.6.0",
|
"redux": "^3.6.0",
|
||||||
"redux-persist": "^4.8.0",
|
"redux-persist": "^4.8.0",
|
||||||
"redux-persist-transform-compress": "^4.2.0",
|
"redux-persist-transform-compress": "^4.2.0",
|
||||||
|
@ -188,7 +187,7 @@
|
||||||
"yarn": "^1.3"
|
"yarn": "^1.3"
|
||||||
},
|
},
|
||||||
"lbrySettings": {
|
"lbrySettings": {
|
||||||
"lbrynetDaemonVersion": "0.37.0rc5",
|
"lbrynetDaemonVersion": "0.37.0",
|
||||||
"lbrynetDaemonUrlTemplate": "https://github.com/lbryio/lbry/releases/download/vDAEMONVER/lbrynet-OSNAME.zip",
|
"lbrynetDaemonUrlTemplate": "https://github.com/lbryio/lbry/releases/download/vDAEMONVER/lbrynet-OSNAME.zip",
|
||||||
"lbrynetDaemonDir": "static/daemon",
|
"lbrynetDaemonDir": "static/daemon",
|
||||||
"lbrynetDaemonFileName": "lbrynet"
|
"lbrynetDaemonFileName": "lbrynet"
|
||||||
|
|
|
@ -36,7 +36,7 @@ export default appState => {
|
||||||
};
|
};
|
||||||
const lbryProto = 'lbry://';
|
const lbryProto = 'lbry://';
|
||||||
const lbryProtoQ = 'lbry://?';
|
const lbryProtoQ = 'lbry://?';
|
||||||
const rendererURL = isDev ? `http://localhost:8080` : `file://${__dirname}/index.html`;
|
const rendererURL = isDev ? `http://localhost:${WEBPACK_PORT}` : `file://${__dirname}/index.html`;
|
||||||
|
|
||||||
let window = new BrowserWindow(windowConfiguration);
|
let window = new BrowserWindow(windowConfiguration);
|
||||||
|
|
||||||
|
|
|
@ -1,5 +1,3 @@
|
||||||
const fs = require('fs');
|
|
||||||
const path = require('path');
|
|
||||||
const chalk = require('chalk');
|
const chalk = require('chalk');
|
||||||
const webpack = require('webpack');
|
const webpack = require('webpack');
|
||||||
const merge = require('webpack-merge');
|
const merge = require('webpack-merge');
|
||||||
|
@ -7,12 +5,9 @@ const middleware = require('webpack-dev-middleware');
|
||||||
const express = require('express');
|
const express = require('express');
|
||||||
const app = express();
|
const app = express();
|
||||||
|
|
||||||
// TODO: Spawn separate threads so realtime status logging can be used
|
// Primary definition for this is in webpack.web.config.js
|
||||||
// without overwriting information/execptions logged by the compilers
|
// We can't access it here because webpack isn't running on this file
|
||||||
const logRealtime = str => {
|
const WEBPACK_PORT = 9090;
|
||||||
let lineCount = (str.match(/\n/) || []).length + 1;
|
|
||||||
console.log('\u001B[' + lineCount + 'F\u001B[G\u001B[2K' + str);
|
|
||||||
};
|
|
||||||
|
|
||||||
console.log(
|
console.log(
|
||||||
chalk.magenta(`Compiling ${chalk.underline('main')} and ${chalk.underline('render')}, this will take a while.`)
|
chalk.magenta(`Compiling ${chalk.underline('main')} and ${chalk.underline('render')}, this will take a while.`)
|
||||||
|
@ -46,8 +41,8 @@ app.use(require('webpack-hot-middleware')(renderCompiler));
|
||||||
app.use(renderInstance);
|
app.use(renderInstance);
|
||||||
app.use(express.static('dist/electron/static'));
|
app.use(express.static('dist/electron/static'));
|
||||||
|
|
||||||
app.listen(8080, () => {
|
app.listen(WEBPACK_PORT, () => {
|
||||||
console.log(chalk.yellow.bold('Renderer listening on port 8080 (still compiling)'));
|
console.log(chalk.yellow.bold(`Renderer listening on port ${WEBPACK_PORT} (still compiling)`));
|
||||||
});
|
});
|
||||||
|
|
||||||
mainInstance.waitUntilValid(() => console.log(chalk.green(`${chalk.underline('main')} compilation complete.`)));
|
mainInstance.waitUntilValid(() => console.log(chalk.green(`${chalk.underline('main')} compilation complete.`)));
|
||||||
|
|
BIN
src/ui/component/channelThumbnail/gerbil.png
Normal file
BIN
src/ui/component/channelThumbnail/gerbil.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 4.6 KiB |
|
@ -1,15 +1,30 @@
|
||||||
// @flow
|
// @flow
|
||||||
import React from 'react';
|
import React from 'react';
|
||||||
|
import { parseURI } from 'lbry-redux';
|
||||||
|
import classnames from 'classnames';
|
||||||
|
import Gerbil from './gerbil.png';
|
||||||
|
|
||||||
type Props = {
|
type Props = {
|
||||||
thumbnail: ?string,
|
thumbnail: ?string,
|
||||||
|
uri: string,
|
||||||
};
|
};
|
||||||
|
|
||||||
function ChannelThumbnail(props: Props) {
|
function ChannelThumbnail(props: Props) {
|
||||||
const { thumbnail } = props;
|
const { thumbnail, uri } = props;
|
||||||
|
|
||||||
|
// Generate a random color class based on the first letter of the channel name
|
||||||
|
const { channelName } = parseURI(uri);
|
||||||
|
const initializer = channelName.charCodeAt(0) - 65; // will be between 0 and 57
|
||||||
|
const className = `channel-thumbnail__default--${initializer % 4}`;
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="channel__thumbnail">
|
<div
|
||||||
{thumbnail && <img className="channel__thumbnail--custom" src={thumbnail} />}
|
className={classnames('channel-thumbnail', {
|
||||||
|
[className]: !thumbnail,
|
||||||
|
})}
|
||||||
|
>
|
||||||
|
{!thumbnail && <img className="channel-thumbnail__default" src={Gerbil} />}
|
||||||
|
{thumbnail && <img className="channel-thumbnail__custom" src={thumbnail} />}
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
|
@ -25,7 +25,7 @@ class IconComponent extends React.PureComponent<Props> {
|
||||||
switch (icon) {
|
switch (icon) {
|
||||||
case ICONS.FEATURED:
|
case ICONS.FEATURED:
|
||||||
return __('Featured content. Earn rewards for watching.');
|
return __('Featured content. Earn rewards for watching.');
|
||||||
case ICONS.LOCAL:
|
case ICONS.DOWNLOAD:
|
||||||
return __('This file is downloaded.');
|
return __('This file is downloaded.');
|
||||||
default:
|
default:
|
||||||
return null;
|
return null;
|
||||||
|
|
|
@ -16,7 +16,7 @@ type Props = {
|
||||||
};
|
};
|
||||||
|
|
||||||
function Paginate(props: Props) {
|
function Paginate(props: Props) {
|
||||||
const { totalPages, loading, location, history, onPageChange } = props;
|
const { totalPages = 1, loading, location, history, onPageChange } = props;
|
||||||
const { search } = location;
|
const { search } = location;
|
||||||
const urlParams = new URLSearchParams(search);
|
const urlParams = new URLSearchParams(search);
|
||||||
const currentPage = Number(urlParams.get(PAGINATE_PARAM)) || 1;
|
const currentPage = Number(urlParams.get(PAGINATE_PARAM)) || 1;
|
||||||
|
|
|
@ -3,19 +3,25 @@ import { Lbryio } from 'lbryinc';
|
||||||
import * as React from 'react';
|
import * as React from 'react';
|
||||||
import Yrbl from 'component/yrbl';
|
import Yrbl from 'component/yrbl';
|
||||||
import Button from 'component/button';
|
import Button from 'component/button';
|
||||||
|
import { withRouter } from 'react-router';
|
||||||
|
|
||||||
type Props = {
|
type Props = {
|
||||||
children: React.Node,
|
children: React.Node,
|
||||||
|
history: {
|
||||||
|
replace: string => void,
|
||||||
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
type State = {
|
type State = {
|
||||||
hasError: boolean,
|
hasError: boolean,
|
||||||
};
|
};
|
||||||
|
|
||||||
export default class ErrorBoundary extends React.Component<Props, State> {
|
class ErrorBoundary extends React.Component<Props, State> {
|
||||||
constructor() {
|
constructor() {
|
||||||
super();
|
super();
|
||||||
this.state = { hasError: false };
|
this.state = { hasError: false };
|
||||||
|
|
||||||
|
(this: any).refresh = this.refresh.bind(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
static getDerivedStateFromError() {
|
static getDerivedStateFromError() {
|
||||||
|
@ -35,6 +41,13 @@ export default class ErrorBoundary extends React.Component<Props, State> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
refresh() {
|
||||||
|
const { history } = this.props;
|
||||||
|
// use history.replace instead of history.push so the user can't click back to the errored page
|
||||||
|
history.replace('');
|
||||||
|
this.setState({ hasError: false });
|
||||||
|
}
|
||||||
|
|
||||||
render() {
|
render() {
|
||||||
if (this.state.hasError) {
|
if (this.state.hasError) {
|
||||||
return (
|
return (
|
||||||
|
@ -50,7 +63,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.href = '/')}
|
onClick={this.refresh}
|
||||||
/>{' '}
|
/>{' '}
|
||||||
{__('to fix it')}.
|
{__('to fix it')}.
|
||||||
</p>
|
</p>
|
||||||
|
@ -64,3 +77,5 @@ export default class ErrorBoundary extends React.Component<Props, State> {
|
||||||
return this.props.children;
|
return this.props.children;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export default withRouter(ErrorBoundary);
|
||||||
|
|
|
@ -12,7 +12,6 @@ import { openCopyLinkMenu } from 'util/context-menu';
|
||||||
import DateTime from 'component/dateTime';
|
import DateTime from 'component/dateTime';
|
||||||
import { withRouter } from 'react-router-dom';
|
import { withRouter } from 'react-router-dom';
|
||||||
import { formatLbryUriForWeb } from 'util/uri';
|
import { formatLbryUriForWeb } from 'util/uri';
|
||||||
import get from 'lodash.get';
|
|
||||||
|
|
||||||
type Props = {
|
type Props = {
|
||||||
uri: string,
|
uri: string,
|
||||||
|
@ -65,7 +64,6 @@ class FileCard extends React.PureComponent<Props> {
|
||||||
const {
|
const {
|
||||||
claim,
|
claim,
|
||||||
fileInfo,
|
fileInfo,
|
||||||
metadata,
|
|
||||||
rewardedContentClaimIds,
|
rewardedContentClaimIds,
|
||||||
obscureNsfw,
|
obscureNsfw,
|
||||||
claimIsMine,
|
claimIsMine,
|
||||||
|
@ -106,7 +104,6 @@ class FileCard extends React.PureComponent<Props> {
|
||||||
|
|
||||||
const uri = !pending ? normalizeURI(this.props.uri) : this.props.uri;
|
const uri = !pending ? normalizeURI(this.props.uri) : this.props.uri;
|
||||||
const isRewardContent = claim && rewardedContentClaimIds.includes(claim.claim_id);
|
const isRewardContent = claim && rewardedContentClaimIds.includes(claim.claim_id);
|
||||||
const height = claim && claim.height;
|
|
||||||
const handleContextMenu = event => {
|
const handleContextMenu = event => {
|
||||||
event.preventDefault();
|
event.preventDefault();
|
||||||
event.stopPropagation();
|
event.stopPropagation();
|
||||||
|
@ -146,7 +143,7 @@ class FileCard extends React.PureComponent<Props> {
|
||||||
{isRewardContent && <Icon iconColor="red" icon={icons.FEATURED} />}
|
{isRewardContent && <Icon iconColor="red" icon={icons.FEATURED} />}
|
||||||
{isSubscribed && <Icon icon={icons.SUBSCRIPTION} />}
|
{isSubscribed && <Icon icon={icons.SUBSCRIPTION} />}
|
||||||
{claimIsMine && <Icon icon={icons.PUBLISHED} />}
|
{claimIsMine && <Icon icon={icons.PUBLISHED} />}
|
||||||
{!claimIsMine && fileInfo && <Icon icon={icons.LOCAL} />}
|
{!claimIsMine && fileInfo && <Icon icon={icons.DOWNLOAD} />}
|
||||||
{isNew && <span className="badge badge--alert">{__('NEW')}</span>}
|
{isNew && <span className="badge badge--alert">{__('NEW')}</span>}
|
||||||
</div>
|
</div>
|
||||||
</li>
|
</li>
|
||||||
|
|
|
@ -92,7 +92,6 @@ class FileDetails extends PureComponent<Props> {
|
||||||
{__('Downloaded to')}
|
{__('Downloaded to')}
|
||||||
{': '}
|
{': '}
|
||||||
<Button
|
<Button
|
||||||
constrict
|
|
||||||
button="link"
|
button="link"
|
||||||
onClick={() => {
|
onClick={() => {
|
||||||
if (downloadPath) {
|
if (downloadPath) {
|
||||||
|
|
|
@ -47,8 +47,8 @@ class FileTile extends React.PureComponent<Props> {
|
||||||
if (!isResolvingUri && !claim && uri) resolveUri(uri);
|
if (!isResolvingUri && !claim && uri) resolveUri(uri);
|
||||||
}
|
}
|
||||||
|
|
||||||
componentWillReceiveProps(nextProps: Props) {
|
componentDidUpdate() {
|
||||||
const { isResolvingUri, claim, uri, resolveUri } = nextProps;
|
const { isResolvingUri, claim, uri, resolveUri } = this.props;
|
||||||
if (!isResolvingUri && claim === undefined && uri) resolveUri(uri);
|
if (!isResolvingUri && claim === undefined && uri) resolveUri(uri);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -68,7 +68,7 @@ class FileTile extends React.PureComponent<Props> {
|
||||||
{isNew && <span className="badge badge--alert icon">{__('NEW')}</span>}
|
{isNew && <span className="badge badge--alert icon">{__('NEW')}</span>}
|
||||||
{isSubscribed && <Icon icon={ICONS.SUBSCRIPTION} />}
|
{isSubscribed && <Icon icon={ICONS.SUBSCRIPTION} />}
|
||||||
{isRewardContent && <Icon iconColor="red" icon={ICONS.FEATURED} />}
|
{isRewardContent && <Icon iconColor="red" icon={ICONS.FEATURED} />}
|
||||||
{!claimIsMine && isDownloaded && <Icon icon={ICONS.LOCAL} />}
|
{!claimIsMine && isDownloaded && <Icon icon={ICONS.DOWNLOAD} />}
|
||||||
{claimIsMine && <Icon icon={ICONS.PUBLISHED} />}
|
{claimIsMine && <Icon icon={ICONS.PUBLISHED} />}
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
|
|
|
@ -78,7 +78,7 @@ class UserHistoryPage extends React.PureComponent<Props, State> {
|
||||||
|
|
||||||
return historyItems.length ? (
|
return historyItems.length ? (
|
||||||
<React.Fragment>
|
<React.Fragment>
|
||||||
<div className="card__actions card__actions--between">
|
<div className="card__header card__actions card__actions--between">
|
||||||
{Object.keys(itemsSelected).length ? (
|
{Object.keys(itemsSelected).length ? (
|
||||||
<Button button="link" label={__('Delete')} onClick={this.removeSelected} />
|
<Button button="link" label={__('Delete')} onClick={this.removeSelected} />
|
||||||
) : (
|
) : (
|
||||||
|
|
|
@ -29,7 +29,7 @@ type Props = {
|
||||||
nsfw: boolean,
|
nsfw: boolean,
|
||||||
contentIsFree: boolean,
|
contentIsFree: boolean,
|
||||||
fee: {
|
fee: {
|
||||||
amount: number,
|
amount: string,
|
||||||
currency: string,
|
currency: string,
|
||||||
},
|
},
|
||||||
channel: string,
|
channel: string,
|
||||||
|
|
|
@ -14,7 +14,6 @@ import FileListPublished from 'page/fileListPublished';
|
||||||
import TransactionHistoryPage from 'page/transactionHistory';
|
import TransactionHistoryPage from 'page/transactionHistory';
|
||||||
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 SubscriptionsPage from 'page/subscriptions';
|
import SubscriptionsPage from 'page/subscriptions';
|
||||||
import SearchPage from 'page/search';
|
import SearchPage from 'page/search';
|
||||||
import UserHistoryPage from 'page/userHistory';
|
import UserHistoryPage from 'page/userHistory';
|
||||||
|
@ -39,7 +38,6 @@ export default function AppRouter() {
|
||||||
<Switch>
|
<Switch>
|
||||||
<Route path="/" exact component={DiscoverPage} />
|
<Route path="/" exact component={DiscoverPage} />
|
||||||
<Route path={`/$/${PAGES.AUTH}`} exact component={AuthPage} />
|
<Route path={`/$/${PAGES.AUTH}`} exact component={AuthPage} />
|
||||||
<Route path={`/$/${PAGES.BACKUP}`} exact component={BackupPage} />
|
|
||||||
<Route path={`/$/${PAGES.INVITE}`} exact component={InvitePage} />
|
<Route path={`/$/${PAGES.INVITE}`} exact component={InvitePage} />
|
||||||
<Route path={`/$/${PAGES.DOWNLOADED}`} exact component={FileListDownloaded} />
|
<Route path={`/$/${PAGES.DOWNLOADED}`} exact component={FileListDownloaded} />
|
||||||
<Route path={`/$/${PAGES.PUBLISHED}`} exact component={FileListPublished} />
|
<Route path={`/$/${PAGES.PUBLISHED}`} exact component={FileListPublished} />
|
||||||
|
|
|
@ -62,10 +62,10 @@ class SideBar extends React.PureComponent<Props> {
|
||||||
),
|
),
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
...buildLink(PAGES.PUBLISHED, 'Publishes', ICONS.PUBLISHED),
|
...buildLink(PAGES.PUBLISHED, __('Publishes'), ICONS.PUBLISHED),
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
...buildLink(PAGES.HISTORY, 'History', ICONS.HISTORY),
|
...buildLink(PAGES.HISTORY, __('Library'), ICONS.DOWNLOAD),
|
||||||
},
|
},
|
||||||
].map(renderLink)}
|
].map(renderLink)}
|
||||||
</ul>
|
</ul>
|
||||||
|
@ -74,35 +74,30 @@ class SideBar extends React.PureComponent<Props> {
|
||||||
<ul className="navigation__links">
|
<ul className="navigation__links">
|
||||||
{[
|
{[
|
||||||
{
|
{
|
||||||
...buildLink(PAGES.ACCOUNT, 'Overview', ICONS.ACCOUNT),
|
...buildLink(PAGES.ACCOUNT, __('Overview'), ICONS.ACCOUNT),
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
...buildLink(PAGES.INVITE, 'Invite', ICONS.INVITE, shouldShowInviteGuide && __('Check this out!')),
|
...buildLink(PAGES.INVITE, __('Invite'), ICONS.INVITE, shouldShowInviteGuide && __('Check this out!')),
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
...buildLink(PAGES.REWARDS, 'Rewards', ICONS.FEATURED),
|
...buildLink(PAGES.REWARDS, __('Rewards'), ICONS.FEATURED),
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
...buildLink(PAGES.SEND, 'Send & Recieve', ICONS.SEND),
|
...buildLink(PAGES.SEND, __('Send & Recieve'), ICONS.SEND),
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
...buildLink(PAGES.TRANSACTIONS, 'Transactions', ICONS.TRANSACTIONS),
|
...buildLink(PAGES.TRANSACTIONS, __('Transactions'), ICONS.TRANSACTIONS),
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
...buildLink(PAGES.SETTINGS, 'Settings', ICONS.SETTINGS),
|
...buildLink(PAGES.SETTINGS, __('Settings'), ICONS.SETTINGS),
|
||||||
},
|
},
|
||||||
// @if TARGET='app'
|
|
||||||
{
|
|
||||||
...buildLink(PAGES.BACKUP, 'Backup', ICONS.BACKUP),
|
|
||||||
},
|
|
||||||
// @endif
|
|
||||||
].map(renderLink)}
|
].map(renderLink)}
|
||||||
</ul>
|
</ul>
|
||||||
|
|
||||||
<ul className="navigation__links navigation__links--bottom">
|
<ul className="navigation__links navigation__links--bottom">
|
||||||
{[
|
{[
|
||||||
{
|
{
|
||||||
...buildLink(PAGES.HELP, 'Help', ICONS.HELP),
|
...buildLink(PAGES.HELP, __('Help'), ICONS.HELP),
|
||||||
},
|
},
|
||||||
].map(renderLink)}
|
].map(renderLink)}
|
||||||
</ul>
|
</ul>
|
||||||
|
|
|
@ -27,7 +27,7 @@ class SocialShare extends React.PureComponent<Props> {
|
||||||
|
|
||||||
render() {
|
render() {
|
||||||
const { claim, isChannel } = this.props;
|
const { claim, isChannel } = this.props;
|
||||||
const { claim_id: claimId, name: claimName, channel_name: channelName, value } = claim;
|
const { claim_id: claimId, name: claimName, channel_name: channelName } = claim;
|
||||||
|
|
||||||
const { speechShareable, onDone } = this.props;
|
const { speechShareable, onDone } = this.props;
|
||||||
const channelClaimId = claim.signing_channel && claim.signing_channel.claim_id;
|
const channelClaimId = claim.signing_channel && claim.signing_channel.claim_id;
|
||||||
|
@ -70,7 +70,7 @@ class SocialShare extends React.PureComponent<Props> {
|
||||||
<React.Fragment>
|
<React.Fragment>
|
||||||
{speechShareable && (
|
{speechShareable && (
|
||||||
<div className="card__content">
|
<div className="card__content">
|
||||||
<label className="card__subtitle">{__('Web link')}</label>
|
<label className="help">{__('Web link')}</label>
|
||||||
<CopyableText copyable={speechURL} />
|
<CopyableText copyable={speechURL} />
|
||||||
<div className="card__actions card__actions--center">
|
<div className="card__actions card__actions--center">
|
||||||
<ToolTip onComponent body={__('Facebook')}>
|
<ToolTip onComponent body={__('Facebook')}>
|
||||||
|
@ -98,7 +98,7 @@ class SocialShare extends React.PureComponent<Props> {
|
||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
<div className="card__content">
|
<div className="card__content">
|
||||||
<label className="card__subtitle">{__('LBRY App link')}</label>
|
<label className="help">{__('LBRY App link')}</label>
|
||||||
<CopyableText copyable={lbryURL} noSnackbar />
|
<CopyableText copyable={lbryURL} noSnackbar />
|
||||||
<div className="card__actions card__actions--center">
|
<div className="card__actions card__actions--center">
|
||||||
<ToolTip onComponent body={__('Facebook')}>
|
<ToolTip onComponent body={__('Facebook')}>
|
||||||
|
|
|
@ -1,11 +1,17 @@
|
||||||
import { connect } from 'react-redux';
|
import { connect } from 'react-redux';
|
||||||
import { selectClaimedRewardsByTransactionId } from 'lbryinc';
|
import { selectClaimedRewardsByTransactionId } from 'lbryinc';
|
||||||
import { doOpenModal } from 'redux/actions/app';
|
import { doOpenModal } from 'redux/actions/app';
|
||||||
import { selectAllMyClaimsByOutpoint, selectTransactionListFilter, doSetTransactionListFilter } from 'lbry-redux';
|
import {
|
||||||
|
selectAllMyClaimsByOutpoint,
|
||||||
|
selectSupportsByOutpoint,
|
||||||
|
selectTransactionListFilter,
|
||||||
|
doSetTransactionListFilter,
|
||||||
|
} from 'lbry-redux';
|
||||||
import TransactionList from './view';
|
import TransactionList from './view';
|
||||||
|
|
||||||
const select = state => ({
|
const select = state => ({
|
||||||
rewards: selectClaimedRewardsByTransactionId(state),
|
rewards: selectClaimedRewardsByTransactionId(state),
|
||||||
|
mySupports: selectSupportsByOutpoint(state),
|
||||||
myClaims: selectAllMyClaimsByOutpoint(state),
|
myClaims: selectAllMyClaimsByOutpoint(state),
|
||||||
filterSetting: selectTransactionListFilter(state),
|
filterSetting: selectTransactionListFilter(state),
|
||||||
});
|
});
|
||||||
|
|
|
@ -6,7 +6,7 @@ import ButtonTransaction from 'component/common/transaction-link';
|
||||||
import CreditAmount from 'component/common/credit-amount';
|
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, parseURI } from 'lbry-redux';
|
||||||
|
|
||||||
type Props = {
|
type Props = {
|
||||||
transaction: Transaction,
|
transaction: Transaction,
|
||||||
|
@ -42,6 +42,9 @@ class TransactionListItem extends React.PureComponent<Props> {
|
||||||
render() {
|
render() {
|
||||||
const { reward, transaction, isRevokeable } = this.props;
|
const { reward, transaction, isRevokeable } = this.props;
|
||||||
const { amount, claim_id: claimId, claim_name: name, date, fee, txid, type } = transaction;
|
const { amount, claim_id: claimId, claim_name: name, date, fee, txid, type } = transaction;
|
||||||
|
// Ensure the claim name is valid
|
||||||
|
const { claimName } = parseURI(name);
|
||||||
|
|
||||||
const dateFormat = {
|
const dateFormat = {
|
||||||
month: 'short',
|
month: 'short',
|
||||||
day: 'numeric',
|
day: 'numeric',
|
||||||
|
@ -65,9 +68,9 @@ class TransactionListItem extends React.PureComponent<Props> {
|
||||||
</td>
|
</td>
|
||||||
<td className="table__item--actionable">
|
<td className="table__item--actionable">
|
||||||
{reward && <span>{reward.reward_title}</span>}
|
{reward && <span>{reward.reward_title}</span>}
|
||||||
{name && claimId && (
|
{claimName && claimId && (
|
||||||
<Button button="link" navigate={buildURI({ claimName: name, claimId })}>
|
<Button button="link" navigate={buildURI({ claimName: claimName, claimId })}>
|
||||||
{name}
|
{claimName}
|
||||||
</Button>
|
</Button>
|
||||||
)}
|
)}
|
||||||
</td>
|
</td>
|
||||||
|
|
|
@ -14,6 +14,7 @@ type Props = {
|
||||||
transactions: Array<Transaction>,
|
transactions: Array<Transaction>,
|
||||||
rewards: {},
|
rewards: {},
|
||||||
openModal: (id: string, { nout: number, txid: string }) => void,
|
openModal: (id: string, { nout: number, txid: string }) => void,
|
||||||
|
mySupports: {},
|
||||||
myClaims: any,
|
myClaims: any,
|
||||||
filterSetting: string,
|
filterSetting: string,
|
||||||
setTransactionFilter: string => void,
|
setTransactionFilter: string => void,
|
||||||
|
@ -42,10 +43,9 @@ class TransactionList extends React.PureComponent<Props> {
|
||||||
}
|
}
|
||||||
|
|
||||||
isRevokeable(txid: string, nout: number) {
|
isRevokeable(txid: string, nout: number) {
|
||||||
const { myClaims } = this.props;
|
const outpoint = `${txid}:${nout}`;
|
||||||
// a claim/support/update is revokable if it
|
const { mySupports, myClaims } = this.props;
|
||||||
// is in my claim list(claim_list_mine)
|
return !!mySupports[outpoint] || myClaims.has(outpoint);
|
||||||
return myClaims.has(`${txid}:${nout}`);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
revokeClaim(txid: string, nout: number) {
|
revokeClaim(txid: string, nout: number) {
|
||||||
|
|
|
@ -39,6 +39,12 @@ class TransactionListRecent extends React.PureComponent<Props> {
|
||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
|
|
||||||
|
{!fetchingTransactions && !hasTransactions && (
|
||||||
|
<div className="card__content">
|
||||||
|
<p className="card__subtitle">{__('No transactions... yet.')}</p>
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
|
|
||||||
{hasTransactions && (
|
{hasTransactions && (
|
||||||
<Fragment>
|
<Fragment>
|
||||||
<div className="card__content">
|
<div className="card__content">
|
||||||
|
|
|
@ -1,9 +1,9 @@
|
||||||
import { connect } from 'react-redux';
|
import { connect } from 'react-redux';
|
||||||
import { selectDaemonSettings } from 'redux/selectors/settings';
|
import { selectDaemonSettings } from 'redux/selectors/settings';
|
||||||
import BackupPage from './view';
|
import WalletBackup from './view';
|
||||||
|
|
||||||
const select = state => ({
|
const select = state => ({
|
||||||
daemonSettings: selectDaemonSettings(state),
|
daemonSettings: selectDaemonSettings(state),
|
||||||
});
|
});
|
||||||
|
|
||||||
export default connect(select)(BackupPage);
|
export default connect(select)(WalletBackup);
|
66
src/ui/component/walletBackup/view.jsx
Normal file
66
src/ui/component/walletBackup/view.jsx
Normal file
|
@ -0,0 +1,66 @@
|
||||||
|
// @flow
|
||||||
|
import * as React from 'react';
|
||||||
|
import Button from 'component/button';
|
||||||
|
|
||||||
|
type Props = {
|
||||||
|
daemonSettings: {
|
||||||
|
wallet_dir: ?string,
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
class WalletBackup extends React.PureComponent<Props> {
|
||||||
|
render() {
|
||||||
|
const { daemonSettings } = this.props;
|
||||||
|
const { wallet_dir: lbryumWalletDir } = daemonSettings;
|
||||||
|
|
||||||
|
const noDaemonSettings = Object.keys(daemonSettings).length === 0;
|
||||||
|
|
||||||
|
return (
|
||||||
|
<section className="card card--section">
|
||||||
|
{noDaemonSettings ? (
|
||||||
|
<header className="card__header">
|
||||||
|
<h2 className="card__title">{__('Failed to load settings.')}</h2>
|
||||||
|
</header>
|
||||||
|
) : (
|
||||||
|
<React.Fragment>
|
||||||
|
<header className="card__header">
|
||||||
|
<h2 className="card__title">{__('Backup Your LBRY Credits')}</h2>
|
||||||
|
|
||||||
|
<p className="card__subtitle">
|
||||||
|
{__(
|
||||||
|
'Your LBRY credits are controllable by you and only you, via wallet file(s) stored locally on your computer.'
|
||||||
|
)}
|
||||||
|
</p>
|
||||||
|
</header>
|
||||||
|
|
||||||
|
<div className="card__content">
|
||||||
|
<p>
|
||||||
|
{__(
|
||||||
|
'Currently, there is no automatic wallet backup. If you lose access to these files, you will lose your credits permanently.'
|
||||||
|
)}
|
||||||
|
</p>
|
||||||
|
<p>
|
||||||
|
{__(
|
||||||
|
'However, it is fairly easy to back up manually. To backup your wallet, make a copy of the folder listed below:'
|
||||||
|
)}
|
||||||
|
</p>
|
||||||
|
<p className="card__message">{lbryumWalletDir}</p>
|
||||||
|
<p>
|
||||||
|
{__(
|
||||||
|
'Access to these files are equivalent to having access to your credits. Keep any copies you make of your wallet in a secure place.'
|
||||||
|
)}
|
||||||
|
</p>
|
||||||
|
<p>
|
||||||
|
For more details on backing up and best practices,{' '}
|
||||||
|
<Button button="link" href="https://lbry.com/faq/how-to-backup-wallet" label={__('see this article')} />
|
||||||
|
.
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
</React.Fragment>
|
||||||
|
)}
|
||||||
|
</section>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export default WalletBackup;
|
|
@ -92,12 +92,12 @@ class WalletSend extends React.PureComponent<Props> {
|
||||||
parseFloat(values.amount) === balance
|
parseFloat(values.amount) === balance
|
||||||
}
|
}
|
||||||
/>
|
/>
|
||||||
{!!Object.keys(errors).length && (
|
{!!Object.keys(errors).length || (
|
||||||
<span className="error-text">
|
<span className="error-text">
|
||||||
{(!!values.address && touched.address && errors.address) ||
|
{(!!values.address && touched.address && errors.address) ||
|
||||||
(!!values.amount && touched.amount && errors.amount) ||
|
(!!values.amount && touched.amount && errors.amount) ||
|
||||||
(values.amount === balance && __('Decrease amount to account for transaction fee')) ||
|
(parseFloat(values.amount) === balance && __('Decrease amount to account for transaction fee')) ||
|
||||||
(values.amount > balance && __('Not enough credits'))}
|
(parseFloat(values.amount) > balance && __('Not enough credits'))}
|
||||||
</span>
|
</span>
|
||||||
)}
|
)}
|
||||||
</div>
|
</div>
|
||||||
|
|
|
@ -3,7 +3,7 @@ import React, { Suspense } from 'react';
|
||||||
import { Modal } from 'modal/modal';
|
import { Modal } from 'modal/modal';
|
||||||
import Button from 'component/button';
|
import Button from 'component/button';
|
||||||
import UserPhoneVerify from 'component/userPhoneVerify';
|
import UserPhoneVerify from 'component/userPhoneVerify';
|
||||||
import { withRouter } from 'react-router-dom';
|
import { Redirect } from 'react-router';
|
||||||
|
|
||||||
const LazyUserPhoneNew = React.lazy(() =>
|
const LazyUserPhoneNew = React.lazy(() =>
|
||||||
import(/* webpackChunkName: "userPhoneNew" */
|
import(/* webpackChunkName: "userPhoneNew" */
|
||||||
|
@ -13,7 +13,7 @@ const LazyUserPhoneNew = React.lazy(() =>
|
||||||
type Props = {
|
type Props = {
|
||||||
phone: ?number,
|
phone: ?number,
|
||||||
user: {
|
user: {
|
||||||
phone_number: ?number,
|
is_identity_verified: boolean,
|
||||||
},
|
},
|
||||||
closeModal: () => void,
|
closeModal: () => void,
|
||||||
history: { push: string => void },
|
history: { push: string => void },
|
||||||
|
@ -23,29 +23,30 @@ class ModalPhoneCollection extends React.PureComponent<Props> {
|
||||||
getTitle() {
|
getTitle() {
|
||||||
const { user, phone } = this.props;
|
const { user, phone } = this.props;
|
||||||
|
|
||||||
if (!user.phone_number && !phone) {
|
if (!user.is_identity_verified && !phone) {
|
||||||
return __('Enter Your Phone Number');
|
return __('Enter Your Phone Number');
|
||||||
}
|
}
|
||||||
|
|
||||||
return __('Enter The Verification Code');
|
return __('Enter The Verification Code');
|
||||||
}
|
}
|
||||||
|
|
||||||
renderInner() {
|
renderInner() {
|
||||||
const { closeModal, phone, user, history } = this.props;
|
const { closeModal, phone, user } = this.props;
|
||||||
|
|
||||||
const cancelButton = <Button button="link" onClick={closeModal} label={__('Not Now')} />;
|
const cancelButton = <Button button="link" onClick={closeModal} label={__('Not Now')} />;
|
||||||
|
|
||||||
if (!user.phone_number && !phone) {
|
if (!user.is_identity_verified && !phone) {
|
||||||
return (
|
return (
|
||||||
<Suspense fallback={<div />}>
|
<Suspense fallback={<div />}>
|
||||||
<LazyUserPhoneNew cancelButton={cancelButton} />
|
<LazyUserPhoneNew cancelButton={cancelButton} />
|
||||||
</Suspense>
|
</Suspense>
|
||||||
);
|
);
|
||||||
} else if (!user.phone_number) {
|
} else if (!user.is_identity_verified) {
|
||||||
return <UserPhoneVerify cancelButton={cancelButton} />;
|
return <UserPhoneVerify cancelButton={cancelButton} />;
|
||||||
}
|
}
|
||||||
|
|
||||||
history.push('/$/rewards');
|
closeModal();
|
||||||
return closeModal();
|
return <Redirect to="/$/rewards" />;
|
||||||
}
|
}
|
||||||
|
|
||||||
render() {
|
render() {
|
||||||
|
@ -64,4 +65,4 @@ class ModalPhoneCollection extends React.PureComponent<Props> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export default withRouter(ModalPhoneCollection);
|
export default ModalPhoneCollection;
|
||||||
|
|
|
@ -1,73 +0,0 @@
|
||||||
// @flow
|
|
||||||
import * as React from 'react';
|
|
||||||
import Button from 'component/button';
|
|
||||||
import Page from 'component/page';
|
|
||||||
|
|
||||||
type Props = {
|
|
||||||
daemonSettings: {
|
|
||||||
wallet_dir: ?string,
|
|
||||||
},
|
|
||||||
};
|
|
||||||
|
|
||||||
class BackupPage extends React.PureComponent<Props> {
|
|
||||||
render() {
|
|
||||||
const { daemonSettings } = this.props;
|
|
||||||
const { wallet_dir: lbryumWalletDir } = daemonSettings;
|
|
||||||
|
|
||||||
const noDaemonSettings = Object.keys(daemonSettings).length === 0;
|
|
||||||
|
|
||||||
return (
|
|
||||||
<Page>
|
|
||||||
<section className="card card--section">
|
|
||||||
{noDaemonSettings ? (
|
|
||||||
<header className="card__header">
|
|
||||||
<h2 className="card__title">{__('Failed to load settings.')}</h2>
|
|
||||||
</header>
|
|
||||||
) : (
|
|
||||||
<React.Fragment>
|
|
||||||
<header className="card__header">
|
|
||||||
<h2 className="card__title">{__('Backup Your LBRY Credits')}</h2>
|
|
||||||
|
|
||||||
<p className="card__subtitle">
|
|
||||||
{__(
|
|
||||||
'Your LBRY credits are controllable by you and only you, via wallet file(s) stored locally on your computer.'
|
|
||||||
)}
|
|
||||||
</p>
|
|
||||||
</header>
|
|
||||||
|
|
||||||
<div className="card__content">
|
|
||||||
<p>
|
|
||||||
{__(
|
|
||||||
'Currently, there is no automatic wallet backup. If you lose access to these files, you will lose your credits permanently.'
|
|
||||||
)}
|
|
||||||
</p>
|
|
||||||
<p>
|
|
||||||
{__(
|
|
||||||
'However, it is fairly easy to back up manually. To backup your wallet, make a copy of the folder listed below:'
|
|
||||||
)}
|
|
||||||
</p>
|
|
||||||
<p className="card__message">{lbryumWalletDir}</p>
|
|
||||||
<p>
|
|
||||||
{__(
|
|
||||||
'Access to these files are equivalent to having access to your credits. Keep any copies you make of your wallet in a secure place.'
|
|
||||||
)}
|
|
||||||
</p>
|
|
||||||
<p>
|
|
||||||
For more details on backing up and best practices,{' '}
|
|
||||||
<Button
|
|
||||||
button="link"
|
|
||||||
href="https://lbry.com/faq/how-to-backup-wallet"
|
|
||||||
label={__('see this article')}
|
|
||||||
/>
|
|
||||||
.
|
|
||||||
</p>
|
|
||||||
</div>
|
|
||||||
</React.Fragment>
|
|
||||||
)}
|
|
||||||
</section>
|
|
||||||
</Page>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
export default BackupPage;
|
|
|
@ -4,6 +4,7 @@ import {
|
||||||
makeSelectTitleForUri,
|
makeSelectTitleForUri,
|
||||||
makeSelectThumbnailForUri,
|
makeSelectThumbnailForUri,
|
||||||
makeSelectCoverForUri,
|
makeSelectCoverForUri,
|
||||||
|
selectCurrentChannelPage,
|
||||||
} from 'lbry-redux';
|
} from 'lbry-redux';
|
||||||
import ChannelPage from './view';
|
import ChannelPage from './view';
|
||||||
|
|
||||||
|
@ -12,6 +13,7 @@ const select = (state, props) => ({
|
||||||
thumbnail: makeSelectThumbnailForUri(props.uri)(state),
|
thumbnail: makeSelectThumbnailForUri(props.uri)(state),
|
||||||
cover: makeSelectCoverForUri(props.uri)(state),
|
cover: makeSelectCoverForUri(props.uri)(state),
|
||||||
channelIsMine: makeSelectClaimIsMine(props.uri)(state),
|
channelIsMine: makeSelectClaimIsMine(props.uri)(state),
|
||||||
|
page: selectCurrentChannelPage(state),
|
||||||
});
|
});
|
||||||
|
|
||||||
export default connect(
|
export default connect(
|
||||||
|
|
|
@ -19,13 +19,14 @@ type Props = {
|
||||||
title: ?string,
|
title: ?string,
|
||||||
cover: ?string,
|
cover: ?string,
|
||||||
thumbnail: ?string,
|
thumbnail: ?string,
|
||||||
|
page: number,
|
||||||
location: { search: string },
|
location: { search: string },
|
||||||
history: { push: string => void },
|
history: { push: string => void },
|
||||||
match: { params: { attribute: ?string } },
|
match: { params: { attribute: ?string } },
|
||||||
};
|
};
|
||||||
|
|
||||||
function ChannelPage(props: Props) {
|
function ChannelPage(props: Props) {
|
||||||
const { uri, title, cover, history, location } = props;
|
const { uri, title, cover, history, location, page } = props;
|
||||||
const { channelName, claimName, claimId } = parseURI(uri);
|
const { channelName, claimName, claimId } = parseURI(uri);
|
||||||
const { search } = location;
|
const { search } = location;
|
||||||
const urlParams = new URLSearchParams(search);
|
const urlParams = new URLSearchParams(search);
|
||||||
|
@ -37,17 +38,20 @@ function ChannelPage(props: Props) {
|
||||||
const tabIndex = currentView === ABOUT_PAGE ? 1 : 0;
|
const tabIndex = currentView === ABOUT_PAGE ? 1 : 0;
|
||||||
const onTabChange = newTabIndex => {
|
const onTabChange = newTabIndex => {
|
||||||
let url = formatLbryUriForWeb(uri);
|
let url = formatLbryUriForWeb(uri);
|
||||||
|
let search = '?';
|
||||||
if (newTabIndex !== 0) {
|
if (newTabIndex !== 0) {
|
||||||
url += `?${PAGE_VIEW_QUERY}=${ABOUT_PAGE}`;
|
search += `${PAGE_VIEW_QUERY}=${ABOUT_PAGE}`;
|
||||||
|
} else {
|
||||||
|
search += `page=${page}`;
|
||||||
}
|
}
|
||||||
|
|
||||||
history.push(url);
|
history.push(`${url}${search}`);
|
||||||
};
|
};
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Page notContained className="main--no-padding-top">
|
<Page notContained className="main--no-padding-top">
|
||||||
<header className="channel__cover main__item--extend-outside">
|
<header className="channel-cover main__item--extend-outside">
|
||||||
{cover && <img className="channel__cover--custom" src={cover} />}
|
{cover && <img className="channel-cover__custom" src={cover} />}
|
||||||
|
|
||||||
<div className="channel__primary-info">
|
<div className="channel__primary-info">
|
||||||
<ChannelThumbnail uri={uri} />
|
<ChannelThumbnail uri={uri} />
|
||||||
|
|
|
@ -16,6 +16,7 @@ import {
|
||||||
makeSelectTitleForUri,
|
makeSelectTitleForUri,
|
||||||
makeSelectThumbnailForUri,
|
makeSelectThumbnailForUri,
|
||||||
makeSelectClaimIsNsfw,
|
makeSelectClaimIsNsfw,
|
||||||
|
doToast,
|
||||||
} from 'lbry-redux';
|
} from 'lbry-redux';
|
||||||
import { doFetchViewCount, makeSelectViewCountForUri, makeSelectCostInfoForUri, doFetchCostInfoForUri } from 'lbryinc';
|
import { doFetchViewCount, makeSelectViewCountForUri, makeSelectCostInfoForUri, doFetchCostInfoForUri } from 'lbryinc';
|
||||||
import { selectShowNsfw, makeSelectClientSetting } from 'redux/selectors/settings';
|
import { selectShowNsfw, makeSelectClientSetting } from 'redux/selectors/settings';
|
||||||
|
@ -53,6 +54,7 @@ const perform = dispatch => ({
|
||||||
setViewed: uri => dispatch(doSetContentHistoryItem(uri)),
|
setViewed: uri => dispatch(doSetContentHistoryItem(uri)),
|
||||||
markSubscriptionRead: (channel, uri) => dispatch(doRemoveUnreadSubscription(channel, uri)),
|
markSubscriptionRead: (channel, uri) => dispatch(doRemoveUnreadSubscription(channel, uri)),
|
||||||
fetchViewCount: claimId => dispatch(doFetchViewCount(claimId)),
|
fetchViewCount: claimId => dispatch(doFetchViewCount(claimId)),
|
||||||
|
showToast: options => dispatch(doToast(options)),
|
||||||
});
|
});
|
||||||
|
|
||||||
export default connect(
|
export default connect(
|
||||||
|
|
|
@ -2,6 +2,7 @@
|
||||||
import * as MODALS from 'constants/modal_types';
|
import * as MODALS from 'constants/modal_types';
|
||||||
import * as icons from 'constants/icons';
|
import * as icons from 'constants/icons';
|
||||||
import * as React from 'react';
|
import * as React from 'react';
|
||||||
|
import { clipboard } from 'electron';
|
||||||
import { buildURI, normalizeURI } from 'lbry-redux';
|
import { buildURI, normalizeURI } from 'lbry-redux';
|
||||||
import FileViewer from 'component/fileViewer';
|
import FileViewer from 'component/fileViewer';
|
||||||
import Thumbnail from 'component/common/thumbnail';
|
import Thumbnail from 'component/common/thumbnail';
|
||||||
|
@ -22,7 +23,6 @@ import RecommendedContent from 'component/recommendedContent';
|
||||||
type Props = {
|
type Props = {
|
||||||
claim: StreamClaim,
|
claim: StreamClaim,
|
||||||
fileInfo: FileListItem,
|
fileInfo: FileListItem,
|
||||||
metadata: StreamMetadata,
|
|
||||||
contentType: string,
|
contentType: string,
|
||||||
uri: string,
|
uri: string,
|
||||||
rewardedContentClaimIds: Array<string>,
|
rewardedContentClaimIds: Array<string>,
|
||||||
|
@ -44,6 +44,7 @@ type Props = {
|
||||||
title: string,
|
title: string,
|
||||||
thumbnail: ?string,
|
thumbnail: ?string,
|
||||||
nsfw: boolean,
|
nsfw: boolean,
|
||||||
|
showToast: ({}) => void,
|
||||||
};
|
};
|
||||||
|
|
||||||
class FilePage extends React.Component<Props> {
|
class FilePage extends React.Component<Props> {
|
||||||
|
@ -125,7 +126,6 @@ class FilePage extends React.Component<Props> {
|
||||||
render() {
|
render() {
|
||||||
const {
|
const {
|
||||||
claim,
|
claim,
|
||||||
metadata,
|
|
||||||
contentType,
|
contentType,
|
||||||
uri,
|
uri,
|
||||||
rewardedContentClaimIds,
|
rewardedContentClaimIds,
|
||||||
|
@ -141,10 +141,11 @@ class FilePage extends React.Component<Props> {
|
||||||
title,
|
title,
|
||||||
thumbnail,
|
thumbnail,
|
||||||
nsfw,
|
nsfw,
|
||||||
|
showToast,
|
||||||
} = this.props;
|
} = this.props;
|
||||||
|
|
||||||
// File info
|
// File info
|
||||||
const { height, channel_name: channelName } = claim;
|
const { channel_name: channelName } = claim;
|
||||||
const { PLAYABLE_MEDIA_TYPES, PREVIEW_MEDIA_TYPES } = FilePage;
|
const { PLAYABLE_MEDIA_TYPES, PREVIEW_MEDIA_TYPES } = FilePage;
|
||||||
const isRewardContent = (rewardedContentClaimIds || []).includes(claim.claim_id);
|
const isRewardContent = (rewardedContentClaimIds || []).includes(claim.claim_id);
|
||||||
const shouldObscureThumbnail = obscureNsfw && nsfw;
|
const shouldObscureThumbnail = obscureNsfw && nsfw;
|
||||||
|
@ -175,7 +176,17 @@ 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>
|
<Button
|
||||||
|
className="media__uri"
|
||||||
|
button="alt"
|
||||||
|
label={uri}
|
||||||
|
onClick={() => {
|
||||||
|
clipboard.writeText(uri);
|
||||||
|
showToast({
|
||||||
|
message: __('Text copied'),
|
||||||
|
});
|
||||||
|
}}
|
||||||
|
/>
|
||||||
{!fileInfo && insufficientCredits && (
|
{!fileInfo && insufficientCredits && (
|
||||||
<div className="media__insufficient-credits help--warning">
|
<div className="media__insufficient-credits help--warning">
|
||||||
{__(
|
{__(
|
||||||
|
|
|
@ -2,7 +2,6 @@
|
||||||
// @flow
|
// @flow
|
||||||
import * as icons from 'constants/icons';
|
import * as icons from 'constants/icons';
|
||||||
import * as React from 'react';
|
import * as React from 'react';
|
||||||
import classnames from 'classnames';
|
|
||||||
// @if TARGET='app'
|
// @if TARGET='app'
|
||||||
import { shell } from 'electron';
|
import { shell } from 'electron';
|
||||||
// @endif
|
// @endif
|
||||||
|
@ -10,6 +9,7 @@ import { Lbry } from 'lbry-redux';
|
||||||
import Native from 'native';
|
import Native from 'native';
|
||||||
import Button from 'component/button';
|
import Button from 'component/button';
|
||||||
import Page from 'component/page';
|
import Page from 'component/page';
|
||||||
|
import BackupSection from 'component/walletBackup';
|
||||||
|
|
||||||
type DeamonSettings = {
|
type DeamonSettings = {
|
||||||
data_dir: string | any,
|
data_dir: string | any,
|
||||||
|
@ -194,6 +194,10 @@ class HelpPage extends React.PureComponent<Props, State> {
|
||||||
</div>
|
</div>
|
||||||
</section>
|
</section>
|
||||||
|
|
||||||
|
{/* @if TARGET='app' */}
|
||||||
|
<BackupSection />
|
||||||
|
{/* @endif */}
|
||||||
|
|
||||||
<section className="card card--section">
|
<section className="card card--section">
|
||||||
<header className="card__header">
|
<header className="card__header">
|
||||||
<h2 className="card__title">{__('About')}</h2>
|
<h2 className="card__title">{__('About')}</h2>
|
||||||
|
|
|
@ -39,7 +39,7 @@ export default function SearchPage(props: Props) {
|
||||||
<Fragment>
|
<Fragment>
|
||||||
{isValid && (
|
{isValid && (
|
||||||
<header className="search__header">
|
<header className="search__header">
|
||||||
<Button navigate={uri} className="media__uri">
|
<Button button="alt" navigate={uri} className="media__uri">
|
||||||
{uri}
|
{uri}
|
||||||
</Button>
|
</Button>
|
||||||
{isChannel ? (
|
{isChannel ? (
|
||||||
|
@ -52,7 +52,6 @@ export default function SearchPage(props: Props) {
|
||||||
|
|
||||||
<div className="search__results-wrapper">
|
<div className="search__results-wrapper">
|
||||||
<SearchOptions />
|
<SearchOptions />
|
||||||
|
|
||||||
<FileListSearch query={urlQuery} />
|
<FileListSearch query={urlQuery} />
|
||||||
<div className="card__content help">{__('These search results are provided by LBRY, Inc.')}</div>
|
<div className="card__content help">{__('These search results are provided by LBRY, Inc.')}</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
@ -35,7 +35,7 @@ export function doDeleteFile(outpoint, deleteFromComputer, abandonClaim) {
|
||||||
if (abandonClaim && myClaimsOutpoints.indexOf(outpoint) !== -1) {
|
if (abandonClaim && myClaimsOutpoints.indexOf(outpoint) !== -1) {
|
||||||
const [txid, nout] = outpoint.split(':');
|
const [txid, nout] = outpoint.split(':');
|
||||||
|
|
||||||
dispatch(doAbandonClaim(txid, nout));
|
dispatch(doAbandonClaim(txid, Number(nout)));
|
||||||
}
|
}
|
||||||
|
|
||||||
dispatch({
|
dispatch({
|
||||||
|
|
|
@ -43,7 +43,6 @@ export const doResetThumbnailStatus = () => (dispatch: Dispatch) => {
|
||||||
data: {
|
data: {
|
||||||
uploadThumbnailStatus: THUMBNAIL_STATUSES.READY,
|
uploadThumbnailStatus: THUMBNAIL_STATUSES.READY,
|
||||||
thumbnail: '',
|
thumbnail: '',
|
||||||
nsfw: false,
|
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
})
|
})
|
||||||
|
@ -53,7 +52,6 @@ export const doResetThumbnailStatus = () => (dispatch: Dispatch) => {
|
||||||
data: {
|
data: {
|
||||||
uploadThumbnailStatus: THUMBNAIL_STATUSES.API_DOWN,
|
uploadThumbnailStatus: THUMBNAIL_STATUSES.API_DOWN,
|
||||||
thumbnail: '',
|
thumbnail: '',
|
||||||
nsfw: false,
|
|
||||||
},
|
},
|
||||||
})
|
})
|
||||||
);
|
);
|
||||||
|
|
|
@ -1,6 +1,5 @@
|
||||||
.card {
|
.card {
|
||||||
background-color: $lbry-white;
|
background-color: $lbry-white;
|
||||||
border: 1px solid $lbry-gray-1;
|
|
||||||
margin-bottom: var(--spacing-vertical-xlarge);
|
margin-bottom: var(--spacing-vertical-xlarge);
|
||||||
position: relative;
|
position: relative;
|
||||||
border-radius: var(--card-radius);
|
border-radius: var(--card-radius);
|
||||||
|
@ -8,7 +7,6 @@
|
||||||
|
|
||||||
html[data-mode='dark'] & {
|
html[data-mode='dark'] & {
|
||||||
background-color: rgba($lbry-white, 0.1);
|
background-color: rgba($lbry-white, 0.1);
|
||||||
border-color: rgba($lbry-white, 0.1);
|
|
||||||
box-shadow: var(--card-box-shadow) darken($lbry-gray-1, 80%);
|
box-shadow: var(--card-box-shadow) darken($lbry-gray-1, 80%);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -125,15 +123,15 @@
|
||||||
// Depending on screen width, the amount of items in
|
// Depending on screen width, the amount of items in
|
||||||
// each row change and are auto-sized
|
// each row change and are auto-sized
|
||||||
|
|
||||||
@media (min-width: 2001px) {
|
// @media (min-width: 2001px) {
|
||||||
grid-template-columns: repeat(auto-fill, minmax(calc(100% / 10), 1fr));
|
// grid-template-columns: repeat(auto-fill, minmax(calc(100% / 10), 1fr));
|
||||||
}
|
// }
|
||||||
|
|
||||||
@media (min-width: 1801px) and (max-width: 2000px) {
|
// @media (min-width: 1801px) and (max-width: 2000px) {
|
||||||
grid-template-columns: repeat(auto-fill, minmax(calc(100% / 8), 1fr));
|
// grid-template-columns: repeat(auto-fill, minmax(calc(100% / 8), 1fr));
|
||||||
}
|
// }
|
||||||
|
|
||||||
@media (min-width: 1551px) and (max-width: 1800px) {
|
@media (min-width: 1551px) {
|
||||||
grid-template-columns: repeat(auto-fill, minmax(calc(100% / 7), 1fr));
|
grid-template-columns: repeat(auto-fill, minmax(calc(100% / 7), 1fr));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
$cover-z-index: 0;
|
$cover-z-index: 0;
|
||||||
$metadata-z-index: 1;
|
$metadata-z-index: 1;
|
||||||
|
|
||||||
.channel__cover {
|
.channel-cover {
|
||||||
background-image: linear-gradient(to right, $lbry-indigo-4, $lbry-cyan-5 80%);
|
background-image: linear-gradient(to right, $lbry-indigo-4, $lbry-cyan-5 80%);
|
||||||
display: flex;
|
display: flex;
|
||||||
align-items: flex-end;
|
align-items: flex-end;
|
||||||
|
@ -9,41 +9,62 @@ $metadata-z-index: 1;
|
||||||
color: $lbry-white;
|
color: $lbry-white;
|
||||||
}
|
}
|
||||||
|
|
||||||
.channel__cover--custom {
|
.channel-cover__custom {
|
||||||
z-index: $cover-z-index;
|
z-index: $cover-z-index;
|
||||||
align-self: flex-start;
|
align-self: flex-start;
|
||||||
position: absolute;
|
position: absolute;
|
||||||
object-fit: cover;
|
object-fit: cover;
|
||||||
filter: brightness(40%);
|
filter: brightness(60%);
|
||||||
}
|
}
|
||||||
|
|
||||||
.channel__cover,
|
.channel-cover,
|
||||||
.channel__cover--custom {
|
.channel-cover__custom {
|
||||||
height: var(--cover-photo-height);
|
height: var(--cover-photo-height);
|
||||||
width: 100%;
|
width: 100%;
|
||||||
}
|
}
|
||||||
|
|
||||||
.channel__thumbnail {
|
.channel-thumbnail {
|
||||||
position: absolute;
|
position: absolute;
|
||||||
|
display: flex;
|
||||||
left: var(--spacing-main-padding);
|
left: var(--spacing-main-padding);
|
||||||
height: var(--channel-thumbnail-size);
|
height: var(--channel-thumbnail-size);
|
||||||
width: var(--channel-thumbnail-size);
|
width: var(--channel-thumbnail-size);
|
||||||
background-color: $lbry-gray-3;
|
|
||||||
background-image: linear-gradient(to right, $lbry-white, $lbry-gray-3 80%);
|
|
||||||
background-size: cover;
|
background-size: cover;
|
||||||
box-shadow: 0px 8px 40px -3px $lbry-black;
|
box-shadow: 0px 8px 40px -3px $lbry-black;
|
||||||
}
|
}
|
||||||
|
|
||||||
.channel__thumbnail--custom {
|
.channel-thumbnail__custom {
|
||||||
width: 100%;
|
width: 100%;
|
||||||
object-fit: cover;
|
object-fit: cover;
|
||||||
}
|
}
|
||||||
|
|
||||||
.channel__thumbnail,
|
.channel-thumbnail__default {
|
||||||
.channel__thumbnail--custom {
|
width: 80%;
|
||||||
|
height: 80%;
|
||||||
|
margin-left: auto;
|
||||||
|
margin-right: auto;
|
||||||
|
align-self: flex-end;
|
||||||
|
margin-bottom: -1px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.channel-thumbnail,
|
||||||
|
.channel-thumbnail__custom {
|
||||||
border-radius: var(--card-radius);
|
border-radius: var(--card-radius);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.channel-thumbnail__default--0 {
|
||||||
|
background-color: $lbry-indigo-3;
|
||||||
|
}
|
||||||
|
.channel-thumbnail__default--1 {
|
||||||
|
background-color: $lbry-orange-2;
|
||||||
|
}
|
||||||
|
.channel-thumbnail__default--2 {
|
||||||
|
background-color: $lbry-blue-3;
|
||||||
|
}
|
||||||
|
.channel-thumbnail__default--3 {
|
||||||
|
background-color: $lbry-red-1;
|
||||||
|
}
|
||||||
|
|
||||||
.channel__primary-info {
|
.channel__primary-info {
|
||||||
// Ensure the profile pic/title sit ontop of the default cover background
|
// Ensure the profile pic/title sit ontop of the default cover background
|
||||||
z-index: $metadata-z-index;
|
z-index: $metadata-z-index;
|
||||||
|
@ -61,11 +82,6 @@ $metadata-z-index: 1;
|
||||||
|
|
||||||
.channel__url {
|
.channel__url {
|
||||||
font-size: 1.2rem;
|
font-size: 1.2rem;
|
||||||
user-select: all;
|
|
||||||
margin-top: -0.25rem;
|
margin-top: -0.25rem;
|
||||||
|
color: rgba($lbry-white, 0.75);
|
||||||
}
|
}
|
||||||
|
|
||||||
// .channel__description {
|
|
||||||
// font-size: 1.3rem;
|
|
||||||
// margin: var(--spacing-vertical-large) 0;
|
|
||||||
// }
|
|
||||||
|
|
|
@ -1,6 +1,5 @@
|
||||||
.item-list {
|
.item-list {
|
||||||
background-color: $lbry-white;
|
background-color: $lbry-white;
|
||||||
margin-top: var(--spacing-vertical-large);
|
|
||||||
margin-bottom: var(--spacing-vertical-large);
|
margin-bottom: var(--spacing-vertical-large);
|
||||||
padding: var(--spacing-vertical-large);
|
padding: var(--spacing-vertical-large);
|
||||||
|
|
||||||
|
|
|
@ -30,14 +30,9 @@
|
||||||
position: relative;
|
position: relative;
|
||||||
}
|
}
|
||||||
|
|
||||||
.search__results-title {
|
|
||||||
@extend .media-group__header-title;
|
|
||||||
margin-bottom: var(--spacing-vertical-large);
|
|
||||||
}
|
|
||||||
|
|
||||||
.search__options-wrapper {
|
.search__options-wrapper {
|
||||||
font-size: 1.25em;
|
font-size: 1.25em;
|
||||||
margin-bottom: var(--spacing-vertical-large);
|
margin: var(--spacing-vertical-xlarge) 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
.search__options {
|
.search__options {
|
||||||
|
|
|
@ -29,6 +29,8 @@ table,
|
||||||
}
|
}
|
||||||
|
|
||||||
.table--transactions {
|
.table--transactions {
|
||||||
|
table-layout: fixed;
|
||||||
|
|
||||||
td:nth-of-type(1) {
|
td:nth-of-type(1) {
|
||||||
// TX amounts
|
// TX amounts
|
||||||
font-size: 0.9em;
|
font-size: 0.9em;
|
||||||
|
@ -36,10 +38,13 @@ table,
|
||||||
}
|
}
|
||||||
|
|
||||||
td:nth-of-type(3) {
|
td:nth-of-type(3) {
|
||||||
max-width: 150px;
|
// Only add ellipsis to the links in the table
|
||||||
overflow: hidden;
|
// We still want to show the entire message if a TX includes one
|
||||||
white-space: nowrap;
|
.button__content {
|
||||||
text-overflow: ellipsis;
|
@include constrict(10rem);
|
||||||
|
vertical-align: bottom;
|
||||||
|
display: inline-block;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -77,5 +77,5 @@ $large-breakpoint: 1921px;
|
||||||
// Image
|
// Image
|
||||||
--thumbnail-preview-height: 100px;
|
--thumbnail-preview-height: 100px;
|
||||||
--thumbnail-preview-width: 177px;
|
--thumbnail-preview-width: 177px;
|
||||||
--cover-photo-height: 250px;
|
--cover-photo-height: 300px;
|
||||||
}
|
}
|
||||||
|
|
|
@ -7,6 +7,10 @@
|
||||||
|
|
||||||
<body>
|
<body>
|
||||||
<div id="app"></div>
|
<div id="app"></div>
|
||||||
<script type="text/javascript" src="http://localhost:8080/ui.js"></script>
|
<!--
|
||||||
|
Primary definition for this is in webpack.web.config.js
|
||||||
|
We can't access it here because webpack isn't running on this file
|
||||||
|
-->
|
||||||
|
<script type="text/javascript" src="http://localhost:9090/ui.js"></script>
|
||||||
</body>
|
</body>
|
||||||
</html>
|
</html>
|
||||||
|
|
|
@ -13,6 +13,12 @@ const UI_ROOT = path.resolve(__dirname, 'src/ui/');
|
||||||
const STATIC_ROOT = path.resolve(__dirname, 'static/');
|
const STATIC_ROOT = path.resolve(__dirname, 'static/');
|
||||||
const DIST_ROOT = path.resolve(__dirname, 'dist/');
|
const DIST_ROOT = path.resolve(__dirname, 'dist/');
|
||||||
|
|
||||||
|
// There are a two other uses of this value that can't access it from webpack
|
||||||
|
// They exist in
|
||||||
|
// src/platforms/electron/devServer.js
|
||||||
|
// static/index.dev.html
|
||||||
|
const WEBPACK_PORT = 9090;
|
||||||
|
|
||||||
console.log(ifProduction('production', 'development'));
|
console.log(ifProduction('production', 'development'));
|
||||||
|
|
||||||
let baseConfig = {
|
let baseConfig = {
|
||||||
|
@ -32,6 +38,10 @@ let baseConfig = {
|
||||||
node: {
|
node: {
|
||||||
__dirname: false,
|
__dirname: false,
|
||||||
},
|
},
|
||||||
|
devServer: {
|
||||||
|
historyApiFallback: true,
|
||||||
|
port: WEBPACK_PORT,
|
||||||
|
},
|
||||||
module: {
|
module: {
|
||||||
rules: [
|
rules: [
|
||||||
{
|
{
|
||||||
|
@ -117,6 +127,7 @@ let baseConfig = {
|
||||||
'process.env.NODE_ENV': JSON.stringify(NODE_ENV),
|
'process.env.NODE_ENV': JSON.stringify(NODE_ENV),
|
||||||
'process.env.SDK_API_URL': JSON.stringify(process.env.SDK_API_URL),
|
'process.env.SDK_API_URL': JSON.stringify(process.env.SDK_API_URL),
|
||||||
'process.env.LBRY_API_URL': JSON.stringify(process.env.LBRY_API_URL),
|
'process.env.LBRY_API_URL': JSON.stringify(process.env.LBRY_API_URL),
|
||||||
|
WEBPACK_PORT,
|
||||||
}),
|
}),
|
||||||
],
|
],
|
||||||
};
|
};
|
||||||
|
|
|
@ -18,9 +18,6 @@ const webConfig = {
|
||||||
path: __dirname + '/dist/web',
|
path: __dirname + '/dist/web',
|
||||||
publicPath: '/',
|
publicPath: '/',
|
||||||
},
|
},
|
||||||
devServer: {
|
|
||||||
historyApiFallback: true,
|
|
||||||
},
|
|
||||||
module: {
|
module: {
|
||||||
rules: [
|
rules: [
|
||||||
{
|
{
|
||||||
|
|
27
yarn.lock
27
yarn.lock
|
@ -2389,7 +2389,7 @@ class-utils@^0.3.5:
|
||||||
isobject "^3.0.0"
|
isobject "^3.0.0"
|
||||||
static-extend "^0.1.1"
|
static-extend "^0.1.1"
|
||||||
|
|
||||||
classnames@^2.2.3, classnames@^2.2.5:
|
classnames@^2.2.5:
|
||||||
version "2.2.6"
|
version "2.2.6"
|
||||||
resolved "https://registry.yarnpkg.com/classnames/-/classnames-2.2.6.tgz#43935bffdd291f326dad0a205309b38d00f650ce"
|
resolved "https://registry.yarnpkg.com/classnames/-/classnames-2.2.6.tgz#43935bffdd291f326dad0a205309b38d00f650ce"
|
||||||
integrity sha512-JR/iSQOSt+LQIWwrwEzJ9uk0xfN3mTVYMwt1Ir5mUcSN6pU+V4zQFFaJsclJbPuAUQH+yfWef6tm7l1quW3C8Q==
|
integrity sha512-JR/iSQOSt+LQIWwrwEzJ9uk0xfN3mTVYMwt1Ir5mUcSN6pU+V4zQFFaJsclJbPuAUQH+yfWef6tm7l1quW3C8Q==
|
||||||
|
@ -3540,13 +3540,6 @@ dom-converter@^0.2:
|
||||||
dependencies:
|
dependencies:
|
||||||
utila "~0.4"
|
utila "~0.4"
|
||||||
|
|
||||||
"dom-helpers@^2.4.0 || ^3.0.0":
|
|
||||||
version "3.4.0"
|
|
||||||
resolved "https://registry.yarnpkg.com/dom-helpers/-/dom-helpers-3.4.0.tgz#e9b369700f959f62ecde5a6babde4bccd9169af8"
|
|
||||||
integrity sha512-LnuPJ+dwqKDIyotW1VzmOZ5TONUN7CwkCR5hrgawTUbkBGYdeoNLZo6nNfGkCrjtE1nXXaj7iMMpDa8/d9WoIA==
|
|
||||||
dependencies:
|
|
||||||
"@babel/runtime" "^7.1.2"
|
|
||||||
|
|
||||||
dom-scroll-into-view@^1.2.1:
|
dom-scroll-into-view@^1.2.1:
|
||||||
version "1.2.1"
|
version "1.2.1"
|
||||||
resolved "https://registry.yarnpkg.com/dom-scroll-into-view/-/dom-scroll-into-view-1.2.1.tgz#e8f36732dd089b0201a88d7815dc3f88e6d66c7e"
|
resolved "https://registry.yarnpkg.com/dom-scroll-into-view/-/dom-scroll-into-view-1.2.1.tgz#e8f36732dd089b0201a88d7815dc3f88e6d66c7e"
|
||||||
|
@ -6498,9 +6491,9 @@ lazy-val@^1.0.3, lazy-val@^1.0.4:
|
||||||
yargs "^13.2.2"
|
yargs "^13.2.2"
|
||||||
zstd-codec "^0.1.1"
|
zstd-codec "^0.1.1"
|
||||||
|
|
||||||
lbry-redux@lbryio/lbry-redux#423123f1c19e61cead67c745d0892a2e4481cb6a:
|
lbry-redux@lbryio/lbry-redux#02f6918238110726c0b3b4248c61a84ac0b969e3:
|
||||||
version "0.0.1"
|
version "0.0.1"
|
||||||
resolved "https://codeload.github.com/lbryio/lbry-redux/tar.gz/423123f1c19e61cead67c745d0892a2e4481cb6a"
|
resolved "https://codeload.github.com/lbryio/lbry-redux/tar.gz/02f6918238110726c0b3b4248c61a84ac0b969e3"
|
||||||
dependencies:
|
dependencies:
|
||||||
proxy-polyfill "0.1.6"
|
proxy-polyfill "0.1.6"
|
||||||
reselect "^3.0.0"
|
reselect "^3.0.0"
|
||||||
|
@ -6814,7 +6807,7 @@ longest-streak@^2.0.1:
|
||||||
resolved "https://registry.yarnpkg.com/longest-streak/-/longest-streak-2.0.2.tgz#2421b6ba939a443bb9ffebf596585a50b4c38e2e"
|
resolved "https://registry.yarnpkg.com/longest-streak/-/longest-streak-2.0.2.tgz#2421b6ba939a443bb9ffebf596585a50b4c38e2e"
|
||||||
integrity sha512-TmYTeEYxiAmSVdpbnQDXGtvYOIRsCMg89CVZzwzc2o7GFL1CjoiRPjH5ec0NFAVlAx3fVof9dX/t6KKRAo2OWA==
|
integrity sha512-TmYTeEYxiAmSVdpbnQDXGtvYOIRsCMg89CVZzwzc2o7GFL1CjoiRPjH5ec0NFAVlAx3fVof9dX/t6KKRAo2OWA==
|
||||||
|
|
||||||
loose-envify@^1.0.0, loose-envify@^1.1.0, loose-envify@^1.2.0, loose-envify@^1.3.0, loose-envify@^1.3.1, loose-envify@^1.4.0:
|
loose-envify@^1.0.0, loose-envify@^1.1.0, loose-envify@^1.2.0, loose-envify@^1.3.1, loose-envify@^1.4.0:
|
||||||
version "1.4.0"
|
version "1.4.0"
|
||||||
resolved "https://registry.yarnpkg.com/loose-envify/-/loose-envify-1.4.0.tgz#71ee51fa7be4caec1a63839f7e682d8132d30caf"
|
resolved "https://registry.yarnpkg.com/loose-envify/-/loose-envify-1.4.0.tgz#71ee51fa7be4caec1a63839f7e682d8132d30caf"
|
||||||
integrity sha512-lyuxPGr/Wfhrlem2CL/UcnUc1zcqKAImBDzukY7Y5F/yQiNdko6+fRLevlw1HgMySw7f611UIY408EtxRSoK3Q==
|
integrity sha512-lyuxPGr/Wfhrlem2CL/UcnUc1zcqKAImBDzukY7Y5F/yQiNdko6+fRLevlw1HgMySw7f611UIY408EtxRSoK3Q==
|
||||||
|
@ -9381,18 +9374,6 @@ react-toggle@^4.0.2:
|
||||||
dependencies:
|
dependencies:
|
||||||
classnames "^2.2.5"
|
classnames "^2.2.5"
|
||||||
|
|
||||||
react-virtualized@^9.21.0:
|
|
||||||
version "9.21.0"
|
|
||||||
resolved "https://registry.yarnpkg.com/react-virtualized/-/react-virtualized-9.21.0.tgz#8267c40ffb48db35b242a36dea85edcf280a6506"
|
|
||||||
integrity sha512-duKD2HvO33mqld4EtQKm9H9H0p+xce1c++2D5xn59Ma7P8VT7CprfAe5hwjd1OGkyhqzOZiTMlTal7LxjH5yBQ==
|
|
||||||
dependencies:
|
|
||||||
babel-runtime "^6.26.0"
|
|
||||||
classnames "^2.2.3"
|
|
||||||
dom-helpers "^2.4.0 || ^3.0.0"
|
|
||||||
loose-envify "^1.3.0"
|
|
||||||
prop-types "^15.6.0"
|
|
||||||
react-lifecycles-compat "^3.0.4"
|
|
||||||
|
|
||||||
react@^16.8.2:
|
react@^16.8.2:
|
||||||
version "16.8.6"
|
version "16.8.6"
|
||||||
resolved "https://registry.yarnpkg.com/react/-/react-16.8.6.tgz#ad6c3a9614fd3a4e9ef51117f54d888da01f2bbe"
|
resolved "https://registry.yarnpkg.com/react/-/react-16.8.6.tgz#ad6c3a9614fd3a4e9ef51117f54d888da01f2bbe"
|
||||||
|
|
Loading…
Reference in a new issue