Merge master into 'release'
This commit is contained in:
commit
b7ead10b5b
15 changed files with 120 additions and 36 deletions
|
@ -21,5 +21,6 @@ module.name_mapper='^rewards\(.*\)$' -> '<PROJECT_ROOT>/src/renderer/rewards\1'
|
||||||
module.name_mapper='^modal\(.*\)$' -> '<PROJECT_ROOT>/src/renderer/modal\1'
|
module.name_mapper='^modal\(.*\)$' -> '<PROJECT_ROOT>/src/renderer/modal\1'
|
||||||
module.name_mapper='^app\(.*\)$' -> '<PROJECT_ROOT>/src/renderer/app\1'
|
module.name_mapper='^app\(.*\)$' -> '<PROJECT_ROOT>/src/renderer/app\1'
|
||||||
module.name_mapper='^native\(.*\)$' -> '<PROJECT_ROOT>/src/renderer/native\1'
|
module.name_mapper='^native\(.*\)$' -> '<PROJECT_ROOT>/src/renderer/native\1'
|
||||||
|
module.name_mapper='^analytics\(.*\)$' -> '<PROJECT_ROOT>/src/renderer/analytics\1'
|
||||||
|
|
||||||
[strict]
|
[strict]
|
||||||
|
|
|
@ -50,7 +50,7 @@
|
||||||
"formik": "^0.10.4",
|
"formik": "^0.10.4",
|
||||||
"hast-util-sanitize": "^1.1.2",
|
"hast-util-sanitize": "^1.1.2",
|
||||||
"keytar": "^4.2.1",
|
"keytar": "^4.2.1",
|
||||||
"lbry-redux": "lbryio/lbry-redux#31f7afa8a37f5741dac01fc1ecdf153f3bed95dc",
|
"lbry-redux": "lbryio/lbry-redux#feffbe966fc568cef595ab66b314766261e855df",
|
||||||
"localforage": "^1.7.1",
|
"localforage": "^1.7.1",
|
||||||
"mammoth": "^1.4.6",
|
"mammoth": "^1.4.6",
|
||||||
"mime": "^2.3.1",
|
"mime": "^2.3.1",
|
||||||
|
|
|
@ -2,16 +2,14 @@
|
||||||
import * as React from 'react';
|
import * as React from 'react';
|
||||||
import CardMedia from 'component/cardMedia';
|
import CardMedia from 'component/cardMedia';
|
||||||
import TruncatedText from 'component/common/truncated-text';
|
import TruncatedText from 'component/common/truncated-text';
|
||||||
|
import classnames from 'classnames';
|
||||||
/*
|
import SubscribeButton from 'component/subscribeButton';
|
||||||
This component can probably be combined with FileTile
|
|
||||||
Currently the only difference is showing the number of files/empty channel
|
|
||||||
*/
|
|
||||||
|
|
||||||
type Props = {
|
type Props = {
|
||||||
uri: string,
|
uri: string,
|
||||||
isResolvingUri: boolean,
|
isResolvingUri: boolean,
|
||||||
totalItems: number,
|
totalItems: number,
|
||||||
|
size: string,
|
||||||
claim: ?{
|
claim: ?{
|
||||||
claim_id: string,
|
claim_id: string,
|
||||||
name: string,
|
name: string,
|
||||||
|
@ -21,6 +19,10 @@ type Props = {
|
||||||
};
|
};
|
||||||
|
|
||||||
class ChannelTile extends React.PureComponent<Props> {
|
class ChannelTile extends React.PureComponent<Props> {
|
||||||
|
static defaultProps = {
|
||||||
|
size: 'regular',
|
||||||
|
};
|
||||||
|
|
||||||
componentDidMount() {
|
componentDidMount() {
|
||||||
const { uri, resolveUri } = this.props;
|
const { uri, resolveUri } = this.props;
|
||||||
|
|
||||||
|
@ -36,27 +38,54 @@ class ChannelTile extends React.PureComponent<Props> {
|
||||||
}
|
}
|
||||||
|
|
||||||
render() {
|
render() {
|
||||||
const { claim, navigate, isResolvingUri, totalItems, uri } = this.props;
|
const { claim, navigate, isResolvingUri, totalItems, uri, size } = this.props;
|
||||||
let channelName, channelId;
|
|
||||||
|
|
||||||
|
let channelName;
|
||||||
|
let subscriptionUri;
|
||||||
if (claim) {
|
if (claim) {
|
||||||
channelName = claim.name;
|
channelName = claim.name;
|
||||||
channelId = claim.claim_id;
|
subscriptionUri = claim.permanent_url;
|
||||||
}
|
}
|
||||||
|
|
||||||
const onClick = () => navigate('/show', { uri });
|
const onClick = () => navigate('/show', { uri });
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<section className="file-tile card--link" onClick={onClick} role="button">
|
<section
|
||||||
|
onClick={onClick}
|
||||||
|
role="button"
|
||||||
|
className={classnames('file-tile card--link', {
|
||||||
|
'file-tile--small': size === 'small',
|
||||||
|
'file-tile--large': size === 'large',
|
||||||
|
})}
|
||||||
|
>
|
||||||
<CardMedia title={channelName} thumbnail={null} />
|
<CardMedia title={channelName} thumbnail={null} />
|
||||||
<div className="file-tile__info">
|
<div className="file-tile__info">
|
||||||
{isResolvingUri && <div className="card__title--small">{__('Loading...')}</div>}
|
{isResolvingUri && (
|
||||||
|
<div
|
||||||
|
className={classnames({
|
||||||
|
'card__title--small': size !== 'large',
|
||||||
|
'card__title--large': size === 'large',
|
||||||
|
})}
|
||||||
|
>
|
||||||
|
{__('Loading...')}
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
{!isResolvingUri && (
|
{!isResolvingUri && (
|
||||||
<React.Fragment>
|
<React.Fragment>
|
||||||
<div className="card__title--small card__title--file">
|
<div
|
||||||
|
className={classnames({
|
||||||
|
'card__title--file': size === 'regular',
|
||||||
|
'card__title--x-small': size === 'small',
|
||||||
|
'card__title--large': size === 'large',
|
||||||
|
})}
|
||||||
|
>
|
||||||
<TruncatedText lines={1}>{channelName || uri}</TruncatedText>
|
<TruncatedText lines={1}>{channelName || uri}</TruncatedText>
|
||||||
</div>
|
</div>
|
||||||
<div className="card__subtitle">
|
<div
|
||||||
|
className={classnames('card__subtitle', {
|
||||||
|
'card__subtitle--large': size === 'large',
|
||||||
|
})}
|
||||||
|
>
|
||||||
{totalItems > 0 && (
|
{totalItems > 0 && (
|
||||||
<span>
|
<span>
|
||||||
{totalItems} {totalItems === 1 ? 'file' : 'files'}
|
{totalItems} {totalItems === 1 ? 'file' : 'files'}
|
||||||
|
@ -66,6 +95,11 @@ class ChannelTile extends React.PureComponent<Props> {
|
||||||
</div>
|
</div>
|
||||||
</React.Fragment>
|
</React.Fragment>
|
||||||
)}
|
)}
|
||||||
|
{subscriptionUri && (
|
||||||
|
<div className="card__actions">
|
||||||
|
<SubscribeButton uri={subscriptionUri} channelName={channelName} />
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
</div>
|
</div>
|
||||||
</section>
|
</section>
|
||||||
);
|
);
|
||||||
|
|
|
@ -4,6 +4,7 @@ import {
|
||||||
makeSelectDownloadingForUri,
|
makeSelectDownloadingForUri,
|
||||||
makeSelectLoadingForUri,
|
makeSelectLoadingForUri,
|
||||||
makeSelectCostInfoForUri,
|
makeSelectCostInfoForUri,
|
||||||
|
makeSelectClaimForUri,
|
||||||
} from 'lbry-redux';
|
} from 'lbry-redux';
|
||||||
import { doOpenFileInShell } from 'redux/actions/file';
|
import { doOpenFileInShell } from 'redux/actions/file';
|
||||||
import { doPurchaseUri, doStartDownload } from 'redux/actions/content';
|
import { doPurchaseUri, doStartDownload } from 'redux/actions/content';
|
||||||
|
@ -16,6 +17,7 @@ const select = (state, props) => ({
|
||||||
downloading: makeSelectDownloadingForUri(props.uri)(state),
|
downloading: makeSelectDownloadingForUri(props.uri)(state),
|
||||||
costInfo: makeSelectCostInfoForUri(props.uri)(state),
|
costInfo: makeSelectCostInfoForUri(props.uri)(state),
|
||||||
loading: makeSelectLoadingForUri(props.uri)(state),
|
loading: makeSelectLoadingForUri(props.uri)(state),
|
||||||
|
claim: makeSelectClaimForUri(props.uri)(state),
|
||||||
});
|
});
|
||||||
|
|
||||||
const perform = dispatch => ({
|
const perform = dispatch => ({
|
||||||
|
@ -25,4 +27,7 @@ const perform = dispatch => ({
|
||||||
doPause: () => dispatch(doPause()),
|
doPause: () => dispatch(doPause()),
|
||||||
});
|
});
|
||||||
|
|
||||||
export default connect(select, perform)(FileDownloadLink);
|
export default connect(
|
||||||
|
select,
|
||||||
|
perform
|
||||||
|
)(FileDownloadLink);
|
||||||
|
|
|
@ -3,8 +3,11 @@ import React from 'react';
|
||||||
import Button from 'component/button';
|
import Button from 'component/button';
|
||||||
import * as icons from 'constants/icons';
|
import * as icons from 'constants/icons';
|
||||||
import ToolTip from 'component/common/tooltip';
|
import ToolTip from 'component/common/tooltip';
|
||||||
|
import analytics from 'analytics';
|
||||||
|
import type { Claim } from 'types/claim';
|
||||||
|
|
||||||
type Props = {
|
type Props = {
|
||||||
|
claim: Claim,
|
||||||
uri: string,
|
uri: string,
|
||||||
downloading: boolean,
|
downloading: boolean,
|
||||||
fileInfo: ?{
|
fileInfo: ?{
|
||||||
|
@ -48,6 +51,7 @@ class FileDownloadLink extends React.PureComponent<Props> {
|
||||||
costInfo,
|
costInfo,
|
||||||
loading,
|
loading,
|
||||||
doPause,
|
doPause,
|
||||||
|
claim,
|
||||||
} = this.props;
|
} = this.props;
|
||||||
|
|
||||||
const openFile = () => {
|
const openFile = () => {
|
||||||
|
@ -80,6 +84,12 @@ class FileDownloadLink extends React.PureComponent<Props> {
|
||||||
iconColor="green"
|
iconColor="green"
|
||||||
onClick={() => {
|
onClick={() => {
|
||||||
purchaseUri(uri);
|
purchaseUri(uri);
|
||||||
|
|
||||||
|
const { name, claim_id: claimId, nout, txid } = claim;
|
||||||
|
// // ideally outpoint would exist inside of claim information
|
||||||
|
// // we can use it after https://github.com/lbryio/lbry/issues/1306 is addressed
|
||||||
|
const outpoint = `${txid}:${nout}`;
|
||||||
|
analytics.apiLogView(`${name}#${claimId}`, outpoint, claimId);
|
||||||
}}
|
}}
|
||||||
/>
|
/>
|
||||||
</ToolTip>
|
</ToolTip>
|
||||||
|
|
|
@ -1,10 +1,16 @@
|
||||||
import { connect } from 'react-redux';
|
import { connect } from 'react-redux';
|
||||||
import { makeSelectClaimForUri, doSearch, makeSelectRecommendedContentForUri } from 'lbry-redux';
|
import {
|
||||||
|
makeSelectClaimForUri,
|
||||||
|
doSearch,
|
||||||
|
makeSelectRecommendedContentForUri,
|
||||||
|
selectIsSearching,
|
||||||
|
} from 'lbry-redux';
|
||||||
import RecommendedVideos from './view';
|
import RecommendedVideos from './view';
|
||||||
|
|
||||||
const select = (state, props) => ({
|
const select = (state, props) => ({
|
||||||
claim: makeSelectClaimForUri(props.uri)(state),
|
claim: makeSelectClaimForUri(props.uri)(state),
|
||||||
recommendedContent: makeSelectRecommendedContentForUri(props.uri)(state),
|
recommendedContent: makeSelectRecommendedContentForUri(props.uri)(state),
|
||||||
|
isSearching: selectIsSearching(state),
|
||||||
});
|
});
|
||||||
|
|
||||||
const perform = dispatch => ({
|
const perform = dispatch => ({
|
||||||
|
|
|
@ -7,6 +7,7 @@ type Props = {
|
||||||
uri: string,
|
uri: string,
|
||||||
claim: ?Claim,
|
claim: ?Claim,
|
||||||
recommendedContent: Array<string>,
|
recommendedContent: Array<string>,
|
||||||
|
isSearching: boolean,
|
||||||
search: string => void,
|
search: string => void,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -46,13 +47,12 @@ export default class RecommendedContent extends React.PureComponent<Props> {
|
||||||
didSearch: ?boolean;
|
didSearch: ?boolean;
|
||||||
|
|
||||||
render() {
|
render() {
|
||||||
const { recommendedContent } = this.props;
|
const { recommendedContent, isSearching } = this.props;
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<section className="card__list--recommended">
|
<section className="card__list--recommended">
|
||||||
<span>Related</span>
|
<span>Related</span>
|
||||||
{recommendedContent &&
|
{recommendedContent &&
|
||||||
recommendedContent.length &&
|
|
||||||
recommendedContent.map(recommendedUri => (
|
recommendedContent.map(recommendedUri => (
|
||||||
<FileTile
|
<FileTile
|
||||||
size="small"
|
size="small"
|
||||||
|
@ -62,6 +62,9 @@ export default class RecommendedContent extends React.PureComponent<Props> {
|
||||||
uri={recommendedUri}
|
uri={recommendedUri}
|
||||||
/>
|
/>
|
||||||
))}
|
))}
|
||||||
|
{recommendedContent &&
|
||||||
|
!recommendedContent.length &&
|
||||||
|
!isSearching && <div className="card__subtitle">No related content found</div>}
|
||||||
</section>
|
</section>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
|
@ -41,7 +41,9 @@ export default (props: Props) => {
|
||||||
icon={isSubscribed ? undefined : icons.HEART}
|
icon={isSubscribed ? undefined : icons.HEART}
|
||||||
button="alt"
|
button="alt"
|
||||||
label={subscriptionLabel}
|
label={subscriptionLabel}
|
||||||
onClick={() => {
|
onClick={e => {
|
||||||
|
e.stopPropagation();
|
||||||
|
|
||||||
if (!subscriptions.length) {
|
if (!subscriptions.length) {
|
||||||
doNotify({ id: MODALS.FIRST_SUBSCRIPTION });
|
doNotify({ id: MODALS.FIRST_SUBSCRIPTION });
|
||||||
}
|
}
|
||||||
|
|
|
@ -160,13 +160,6 @@ class FilePage extends React.Component<Props> {
|
||||||
editUri = buildURI(uriObject);
|
editUri = buildURI(uriObject);
|
||||||
}
|
}
|
||||||
|
|
||||||
let recommendedUri = uri;
|
|
||||||
if (!recommendedUri.includes('#')) {
|
|
||||||
// at a vanity url
|
|
||||||
// append the claim ID so we can properly strip it out of reccomended videos
|
|
||||||
recommendedUri = `${recommendedUri}#${claim.claim_id}`;
|
|
||||||
}
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Page forContent>
|
<Page forContent>
|
||||||
<section className="content__wrapper">
|
<section className="content__wrapper">
|
||||||
|
@ -251,7 +244,7 @@ class FilePage extends React.Component<Props> {
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</section>
|
</section>
|
||||||
<RecommendedContent uri={recommendedUri} />
|
<RecommendedContent uri={uri} />
|
||||||
</Page>
|
</Page>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,11 +1,15 @@
|
||||||
// @flow
|
// @flow
|
||||||
import * as React from 'react';
|
import * as React from 'react';
|
||||||
import * as settings from 'constants/settings';
|
import * as settings from 'constants/settings';
|
||||||
import { isURIValid, normalizeURI } from 'lbry-redux';
|
import { isURIValid, normalizeURI, parseURI } from 'lbry-redux';
|
||||||
import { FormField, FormRow } from 'component/common/form';
|
import { FormField, FormRow } from 'component/common/form';
|
||||||
import FileTile from 'component/fileTile';
|
import FileTile from 'component/fileTile';
|
||||||
|
import ChannelTile from 'component/channelTile';
|
||||||
import FileListSearch from 'component/fileListSearch';
|
import FileListSearch from 'component/fileListSearch';
|
||||||
import Page from 'component/page';
|
import Page from 'component/page';
|
||||||
|
import ToolTip from 'component/common/tooltip';
|
||||||
|
import Icon from 'component/common/icon';
|
||||||
|
import * as icons from 'constants/icons';
|
||||||
|
|
||||||
type Props = {
|
type Props = {
|
||||||
query: ?string,
|
query: ?string,
|
||||||
|
@ -32,13 +36,35 @@ class SearchPage extends React.PureComponent<Props> {
|
||||||
|
|
||||||
render() {
|
render() {
|
||||||
const { query, resultCount } = this.props;
|
const { query, resultCount } = this.props;
|
||||||
|
|
||||||
|
const isValid = isURIValid(query);
|
||||||
|
|
||||||
|
let uri;
|
||||||
|
let isChannel;
|
||||||
|
if (isValid) {
|
||||||
|
uri = normalizeURI(query);
|
||||||
|
({ isChannel } = parseURI(uri));
|
||||||
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Page noPadding>
|
<Page noPadding>
|
||||||
{query &&
|
{query &&
|
||||||
isURIValid(query) && (
|
isValid && (
|
||||||
<div className="search__top">
|
<div className="search__top">
|
||||||
<div className="file-list__header">{`lbry://${query}`}</div>
|
<div className="file-list__header">
|
||||||
<FileTile size="large" displayHiddenMessage uri={normalizeURI(query)} />
|
{`lbry://${query}`}
|
||||||
|
<ToolTip
|
||||||
|
icon
|
||||||
|
body={__('This is the resolution of a LBRY URL and not controlled by LBRY Inc.')}
|
||||||
|
>
|
||||||
|
<Icon icon={icons.HELP} />
|
||||||
|
</ToolTip>
|
||||||
|
</div>
|
||||||
|
{isChannel ? (
|
||||||
|
<ChannelTile size="large" uri={uri} />
|
||||||
|
) : (
|
||||||
|
<FileTile size="large" displayHiddenMessage uri={uri} />
|
||||||
|
)}
|
||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
<div className="search__content">
|
<div className="search__content">
|
||||||
|
|
|
@ -278,13 +278,15 @@ export const doCheckPendingPublishes = () => (dispatch: Dispatch, getState: GetS
|
||||||
delete pendingPublishMap[claim.name];
|
delete pendingPublishMap[claim.name];
|
||||||
if (selectosNotificationsEnabled(getState())) {
|
if (selectosNotificationsEnabled(getState())) {
|
||||||
const notif = new window.Notification('LBRY Publish Complete', {
|
const notif = new window.Notification('LBRY Publish Complete', {
|
||||||
body: `${claim.value.stream.metadata.title} has been published to lbry://${claim.name}. Click here to view it` ,
|
body: `${claim.value.stream.metadata.title} has been published to lbry://${
|
||||||
silent: false,
|
claim.name
|
||||||
|
}. Click here to view it`,
|
||||||
|
silent: false,
|
||||||
});
|
});
|
||||||
notif.onclick = () => {
|
notif.onclick = () => {
|
||||||
dispatch(
|
dispatch(
|
||||||
doNavigate('/show', {
|
doNavigate('/show', {
|
||||||
uri: claim.name,
|
uri: claim.permanent_url,
|
||||||
})
|
})
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
|
@ -137,6 +137,7 @@ $large-breakpoint: 1921px;
|
||||||
--search-item-border-color: transparent;
|
--search-item-border-color: transparent;
|
||||||
--search-item-active-color: var(--color-black);
|
--search-item-active-color: var(--color-black);
|
||||||
--search-modal-input-height: 70px;
|
--search-modal-input-height: 70px;
|
||||||
|
--search-exact-result: #eaeaea;
|
||||||
|
|
||||||
/* Nav */
|
/* Nav */
|
||||||
--nav-color: var(--color-grey-dark);
|
--nav-color: var(--color-grey-dark);
|
||||||
|
|
|
@ -87,7 +87,7 @@
|
||||||
|
|
||||||
.search__top {
|
.search__top {
|
||||||
padding: 0 $spacing-width $spacing-width;
|
padding: 0 $spacing-width $spacing-width;
|
||||||
background-color: var(--card-bg);
|
background-color: var(--search-exact-result);
|
||||||
}
|
}
|
||||||
|
|
||||||
.search__content {
|
.search__content {
|
||||||
|
|
|
@ -62,6 +62,7 @@
|
||||||
--search-active-bg-color: #13233C;
|
--search-active-bg-color: #13233C;
|
||||||
--search-active-shadow: 0 6px 9px -2px var(--color-grey--dark);
|
--search-active-shadow: 0 6px 9px -2px var(--color-grey--dark);
|
||||||
--search-modal-input-height: 70px;
|
--search-modal-input-height: 70px;
|
||||||
|
--search-exact-result: #4C5D77;
|
||||||
|
|
||||||
/* Nav */
|
/* Nav */
|
||||||
--nav-color: #44548F;
|
--nav-color: #44548F;
|
||||||
|
|
|
@ -5655,9 +5655,9 @@ lazy-val@^1.0.3:
|
||||||
version "1.0.3"
|
version "1.0.3"
|
||||||
resolved "https://registry.yarnpkg.com/lazy-val/-/lazy-val-1.0.3.tgz#bb97b200ef00801d94c317e29dc6ed39e31c5edc"
|
resolved "https://registry.yarnpkg.com/lazy-val/-/lazy-val-1.0.3.tgz#bb97b200ef00801d94c317e29dc6ed39e31c5edc"
|
||||||
|
|
||||||
lbry-redux@lbryio/lbry-redux#31f7afa8a37f5741dac01fc1ecdf153f3bed95dc:
|
lbry-redux@lbryio/lbry-redux#ccda4117ee503e30abae355c77d3783a141e9492:
|
||||||
version "0.0.1"
|
version "0.0.1"
|
||||||
resolved "https://codeload.github.com/lbryio/lbry-redux/tar.gz/31f7afa8a37f5741dac01fc1ecdf153f3bed95dc"
|
resolved "https://codeload.github.com/lbryio/lbry-redux/tar.gz/ccda4117ee503e30abae355c77d3783a141e9492"
|
||||||
dependencies:
|
dependencies:
|
||||||
proxy-polyfill "0.1.6"
|
proxy-polyfill "0.1.6"
|
||||||
reselect "^3.0.0"
|
reselect "^3.0.0"
|
||||||
|
|
Loading…
Reference in a new issue