diff --git a/.flowconfig b/.flowconfig index 1eaa4969e..c2bb89028 100644 --- a/.flowconfig +++ b/.flowconfig @@ -21,5 +21,6 @@ module.name_mapper='^rewards\(.*\)$' -> '/src/renderer/rewards\1' module.name_mapper='^modal\(.*\)$' -> '/src/renderer/modal\1' module.name_mapper='^app\(.*\)$' -> '/src/renderer/app\1' module.name_mapper='^native\(.*\)$' -> '/src/renderer/native\1' +module.name_mapper='^analytics\(.*\)$' -> '/src/renderer/analytics\1' [strict] diff --git a/package.json b/package.json index 5395917c3..3f0d57ac2 100644 --- a/package.json +++ b/package.json @@ -50,7 +50,7 @@ "formik": "^0.10.4", "hast-util-sanitize": "^1.1.2", "keytar": "^4.2.1", - "lbry-redux": "lbryio/lbry-redux#31f7afa8a37f5741dac01fc1ecdf153f3bed95dc", + "lbry-redux": "lbryio/lbry-redux#feffbe966fc568cef595ab66b314766261e855df", "localforage": "^1.7.1", "mammoth": "^1.4.6", "mime": "^2.3.1", diff --git a/src/renderer/component/channelTile/view.jsx b/src/renderer/component/channelTile/view.jsx index 531b9fccd..4b3c0f744 100644 --- a/src/renderer/component/channelTile/view.jsx +++ b/src/renderer/component/channelTile/view.jsx @@ -2,16 +2,14 @@ import * as React from 'react'; import CardMedia from 'component/cardMedia'; import TruncatedText from 'component/common/truncated-text'; - -/* - This component can probably be combined with FileTile - Currently the only difference is showing the number of files/empty channel -*/ +import classnames from 'classnames'; +import SubscribeButton from 'component/subscribeButton'; type Props = { uri: string, isResolvingUri: boolean, totalItems: number, + size: string, claim: ?{ claim_id: string, name: string, @@ -21,6 +19,10 @@ type Props = { }; class ChannelTile extends React.PureComponent { + static defaultProps = { + size: 'regular', + }; + componentDidMount() { const { uri, resolveUri } = this.props; @@ -36,27 +38,54 @@ class ChannelTile extends React.PureComponent { } render() { - const { claim, navigate, isResolvingUri, totalItems, uri } = this.props; - let channelName, channelId; + const { claim, navigate, isResolvingUri, totalItems, uri, size } = this.props; + let channelName; + let subscriptionUri; if (claim) { channelName = claim.name; - channelId = claim.claim_id; + subscriptionUri = claim.permanent_url; } const onClick = () => navigate('/show', { uri }); return ( -
+
- {isResolvingUri &&
{__('Loading...')}
} + {isResolvingUri && ( +
+ {__('Loading...')} +
+ )} {!isResolvingUri && ( -
+
{channelName || uri}
-
+
{totalItems > 0 && ( {totalItems} {totalItems === 1 ? 'file' : 'files'} @@ -66,6 +95,11 @@ class ChannelTile extends React.PureComponent {
)} + {subscriptionUri && ( +
+ +
+ )}
); diff --git a/src/renderer/component/fileDownloadLink/index.js b/src/renderer/component/fileDownloadLink/index.js index 22f4f0a3f..23ed6b3f7 100644 --- a/src/renderer/component/fileDownloadLink/index.js +++ b/src/renderer/component/fileDownloadLink/index.js @@ -4,6 +4,7 @@ import { makeSelectDownloadingForUri, makeSelectLoadingForUri, makeSelectCostInfoForUri, + makeSelectClaimForUri, } from 'lbry-redux'; import { doOpenFileInShell } from 'redux/actions/file'; import { doPurchaseUri, doStartDownload } from 'redux/actions/content'; @@ -16,6 +17,7 @@ const select = (state, props) => ({ downloading: makeSelectDownloadingForUri(props.uri)(state), costInfo: makeSelectCostInfoForUri(props.uri)(state), loading: makeSelectLoadingForUri(props.uri)(state), + claim: makeSelectClaimForUri(props.uri)(state), }); const perform = dispatch => ({ @@ -25,4 +27,7 @@ const perform = dispatch => ({ doPause: () => dispatch(doPause()), }); -export default connect(select, perform)(FileDownloadLink); +export default connect( + select, + perform +)(FileDownloadLink); diff --git a/src/renderer/component/fileDownloadLink/view.jsx b/src/renderer/component/fileDownloadLink/view.jsx index ccc0f2ba7..bcb352eb2 100644 --- a/src/renderer/component/fileDownloadLink/view.jsx +++ b/src/renderer/component/fileDownloadLink/view.jsx @@ -3,8 +3,11 @@ import React from 'react'; import Button from 'component/button'; import * as icons from 'constants/icons'; import ToolTip from 'component/common/tooltip'; +import analytics from 'analytics'; +import type { Claim } from 'types/claim'; type Props = { + claim: Claim, uri: string, downloading: boolean, fileInfo: ?{ @@ -48,6 +51,7 @@ class FileDownloadLink extends React.PureComponent { costInfo, loading, doPause, + claim, } = this.props; const openFile = () => { @@ -80,6 +84,12 @@ class FileDownloadLink extends React.PureComponent { iconColor="green" onClick={() => { 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); }} /> diff --git a/src/renderer/component/recommendedContent/index.js b/src/renderer/component/recommendedContent/index.js index 166498b6d..36ae3337e 100644 --- a/src/renderer/component/recommendedContent/index.js +++ b/src/renderer/component/recommendedContent/index.js @@ -1,10 +1,16 @@ import { connect } from 'react-redux'; -import { makeSelectClaimForUri, doSearch, makeSelectRecommendedContentForUri } from 'lbry-redux'; +import { + makeSelectClaimForUri, + doSearch, + makeSelectRecommendedContentForUri, + selectIsSearching, +} from 'lbry-redux'; import RecommendedVideos from './view'; const select = (state, props) => ({ claim: makeSelectClaimForUri(props.uri)(state), recommendedContent: makeSelectRecommendedContentForUri(props.uri)(state), + isSearching: selectIsSearching(state), }); const perform = dispatch => ({ diff --git a/src/renderer/component/recommendedContent/view.jsx b/src/renderer/component/recommendedContent/view.jsx index 5248d3859..4a12aecb3 100644 --- a/src/renderer/component/recommendedContent/view.jsx +++ b/src/renderer/component/recommendedContent/view.jsx @@ -7,6 +7,7 @@ type Props = { uri: string, claim: ?Claim, recommendedContent: Array, + isSearching: boolean, search: string => void, }; @@ -46,13 +47,12 @@ export default class RecommendedContent extends React.PureComponent { didSearch: ?boolean; render() { - const { recommendedContent } = this.props; + const { recommendedContent, isSearching } = this.props; return (
Related {recommendedContent && - recommendedContent.length && recommendedContent.map(recommendedUri => ( { uri={recommendedUri} /> ))} + {recommendedContent && + !recommendedContent.length && + !isSearching &&
No related content found
}
); } diff --git a/src/renderer/component/subscribeButton/view.jsx b/src/renderer/component/subscribeButton/view.jsx index a29b8bb4a..4d5727d31 100644 --- a/src/renderer/component/subscribeButton/view.jsx +++ b/src/renderer/component/subscribeButton/view.jsx @@ -41,7 +41,9 @@ export default (props: Props) => { icon={isSubscribed ? undefined : icons.HEART} button="alt" label={subscriptionLabel} - onClick={() => { + onClick={e => { + e.stopPropagation(); + if (!subscriptions.length) { doNotify({ id: MODALS.FIRST_SUBSCRIPTION }); } diff --git a/src/renderer/page/file/view.jsx b/src/renderer/page/file/view.jsx index 6cd38b050..da35a01d1 100644 --- a/src/renderer/page/file/view.jsx +++ b/src/renderer/page/file/view.jsx @@ -160,13 +160,6 @@ class FilePage extends React.Component { 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 (
@@ -251,7 +244,7 @@ class FilePage extends React.Component {
- +
); } diff --git a/src/renderer/page/search/view.jsx b/src/renderer/page/search/view.jsx index 4b2497797..89d8425d7 100644 --- a/src/renderer/page/search/view.jsx +++ b/src/renderer/page/search/view.jsx @@ -1,11 +1,15 @@ // @flow import * as React from 'react'; 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 FileTile from 'component/fileTile'; +import ChannelTile from 'component/channelTile'; import FileListSearch from 'component/fileListSearch'; 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 = { query: ?string, @@ -32,13 +36,35 @@ class SearchPage extends React.PureComponent { render() { const { query, resultCount } = this.props; + + const isValid = isURIValid(query); + + let uri; + let isChannel; + if (isValid) { + uri = normalizeURI(query); + ({ isChannel } = parseURI(uri)); + } + return ( {query && - isURIValid(query) && ( + isValid && (
-
{`lbry://${query}`}
- +
+ {`lbry://${query}`} + + + +
+ {isChannel ? ( + + ) : ( + + )}
)}
diff --git a/src/renderer/redux/actions/publish.js b/src/renderer/redux/actions/publish.js index 1ab5dcab6..8e6c54e42 100644 --- a/src/renderer/redux/actions/publish.js +++ b/src/renderer/redux/actions/publish.js @@ -278,13 +278,15 @@ export const doCheckPendingPublishes = () => (dispatch: Dispatch, getState: GetS delete pendingPublishMap[claim.name]; if (selectosNotificationsEnabled(getState())) { 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` , - silent: false, + body: `${claim.value.stream.metadata.title} has been published to lbry://${ + claim.name + }. Click here to view it`, + silent: false, }); notif.onclick = () => { dispatch( doNavigate('/show', { - uri: claim.name, + uri: claim.permanent_url, }) ); }; diff --git a/src/renderer/scss/_vars.scss b/src/renderer/scss/_vars.scss index ce5caddf4..199809230 100644 --- a/src/renderer/scss/_vars.scss +++ b/src/renderer/scss/_vars.scss @@ -137,6 +137,7 @@ $large-breakpoint: 1921px; --search-item-border-color: transparent; --search-item-active-color: var(--color-black); --search-modal-input-height: 70px; + --search-exact-result: #eaeaea; /* Nav */ --nav-color: var(--color-grey-dark); diff --git a/src/renderer/scss/component/_search.scss b/src/renderer/scss/component/_search.scss index fb61a21e5..fbe3f6a3d 100644 --- a/src/renderer/scss/component/_search.scss +++ b/src/renderer/scss/component/_search.scss @@ -87,7 +87,7 @@ .search__top { padding: 0 $spacing-width $spacing-width; - background-color: var(--card-bg); + background-color: var(--search-exact-result); } .search__content { diff --git a/static/themes/dark.css b/static/themes/dark.css index d3ca442c5..fae053d75 100644 --- a/static/themes/dark.css +++ b/static/themes/dark.css @@ -62,6 +62,7 @@ --search-active-bg-color: #13233C; --search-active-shadow: 0 6px 9px -2px var(--color-grey--dark); --search-modal-input-height: 70px; + --search-exact-result: #4C5D77; /* Nav */ --nav-color: #44548F; diff --git a/yarn.lock b/yarn.lock index 83104ad53..3b366088b 100644 --- a/yarn.lock +++ b/yarn.lock @@ -5655,9 +5655,9 @@ lazy-val@^1.0.3: version "1.0.3" 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" - resolved "https://codeload.github.com/lbryio/lbry-redux/tar.gz/31f7afa8a37f5741dac01fc1ecdf153f3bed95dc" + resolved "https://codeload.github.com/lbryio/lbry-redux/tar.gz/ccda4117ee503e30abae355c77d3783a141e9492" dependencies: proxy-polyfill "0.1.6" reselect "^3.0.0"