diff --git a/lbrytv/package.json b/lbrytv/package.json index d71e2f6cc..6c6d3913d 100644 --- a/lbrytv/package.json +++ b/lbrytv/package.json @@ -31,8 +31,8 @@ "koa-logger": "^3.2.1", "koa-send": "^5.0.0", "koa-static": "^5.0.0", - "lbry-redux": "lbryio/lbry-redux#87ae7faf1c1d5ffa86feb578899596f6ea2a5fd9", - "lbryinc": "lbryio/lbryinc#0addc624db54000b0447f4539f91f5758d26eef3", + "lbry-redux": "lbryio/lbry-redux#f6e5b69e5aa337d50503a2f5ebb5efe4eda4ac57", + "lbryinc": "lbryio/lbryinc#6a52f8026cdc7cd56d200fb5c46f852e0139bbeb", "mysql": "^2.17.1", "node-fetch": "^2.6.0" }, diff --git a/lbrytv/yarn.lock b/lbrytv/yarn.lock index 666885265..b30af630d 100644 --- a/lbrytv/yarn.lock +++ b/lbrytv/yarn.lock @@ -3333,17 +3333,17 @@ latest-version@^3.0.0: dependencies: package-json "^4.0.0" -lbry-redux@lbryio/lbry-redux#87ae7faf1c1d5ffa86feb578899596f6ea2a5fd9: +lbry-redux@lbryio/lbry-redux#f6e5b69e5aa337d50503a2f5ebb5efe4eda4ac57: version "0.0.1" - resolved "https://codeload.github.com/lbryio/lbry-redux/tar.gz/87ae7faf1c1d5ffa86feb578899596f6ea2a5fd9" + resolved "https://codeload.github.com/lbryio/lbry-redux/tar.gz/f6e5b69e5aa337d50503a2f5ebb5efe4eda4ac57" dependencies: proxy-polyfill "0.1.6" reselect "^3.0.0" uuid "^3.3.2" -lbryinc@lbryio/lbryinc#0addc624db54000b0447f4539f91f5758d26eef3: +lbryinc@lbryio/lbryinc#6a52f8026cdc7cd56d200fb5c46f852e0139bbeb: version "0.0.1" - resolved "https://codeload.github.com/lbryio/lbryinc/tar.gz/0addc624db54000b0447f4539f91f5758d26eef3" + resolved "https://codeload.github.com/lbryio/lbryinc/tar.gz/6a52f8026cdc7cd56d200fb5c46f852e0139bbeb" dependencies: reselect "^3.0.0" diff --git a/package.json b/package.json index ec33734f1..37af1ca8c 100644 --- a/package.json +++ b/package.json @@ -70,7 +70,7 @@ "@babel/register": "^7.0.0", "@exponent/electron-cookies": "^2.0.0", "@hot-loader/react-dom": "^16.8", - "@lbry/components": "^4.1.5", + "@lbry/components": "^4.2.2", "@reach/menu-button": "0.7.4", "@reach/rect": "^0.2.1", "@reach/tabs": "^0.1.5", @@ -132,8 +132,8 @@ "imagesloaded": "^4.1.4", "json-loader": "^0.5.4", "lbry-format": "https://github.com/lbryio/lbry-format.git", - "lbry-redux": "lbryio/lbry-redux#cd9c15567f2934ddc82de364d88b378ff04d5571", - "lbryinc": "lbryio/lbryinc#cc62a4eec10845cc0b31da7d0f27287cfa7c4866", + "lbry-redux": "lbryio/lbry-redux#aa2cfa789670e899824d3d3ac1ae677172a7ad4e", + "lbryinc": "lbryio/lbryinc#6a52f8026cdc7cd56d200fb5c46f852e0139bbeb", "lint-staged": "^7.0.2", "localforage": "^1.7.1", "lodash-es": "^4.17.14", @@ -211,7 +211,7 @@ "yarn": "^1.3" }, "lbrySettings": { - "lbrynetDaemonVersion": "0.72.0", + "lbrynetDaemonVersion": "0.74.0", "lbrynetDaemonUrlTemplate": "https://github.com/lbryio/lbry/releases/download/vDAEMONVER/lbrynet-OSNAME.zip", "lbrynetDaemonDir": "static/daemon", "lbrynetDaemonFileName": "lbrynet" diff --git a/ui/analytics.js b/ui/analytics.js index 1e6fc76f8..01a3d1514 100644 --- a/ui/analytics.js +++ b/ui/analytics.js @@ -30,7 +30,7 @@ if (isProduction) { type Analytics = { error: string => Promise, - sentryError: ({}, {}) => Promise, + sentryError: ({} | string, {}) => Promise, pageView: string => void, setUser: Object => void, toggleInternal: (boolean, ?boolean) => void, @@ -45,6 +45,7 @@ type Analytics = { emailVerifiedEvent: () => void, rewardEligibleEvent: () => void, startupEvent: () => void, + purchaseEvent: number => void, readyEvent: number => void, openUrlEvent: string => void, }; @@ -217,6 +218,9 @@ const analytics: Analytics = { sendGaEvent('Startup', 'App-Ready'); sendGaTimingEvent('Startup', 'App-Ready', timeToReady); }, + purchaseEvent: (purchaseInt: number) => { + sendGaEvent('Purchase', 'Purchase-Complete', undefined, purchaseInt); + }, }; function sendGaEvent(category, action, label, value) { diff --git a/ui/component/claimInsufficientCredits/index.js b/ui/component/claimInsufficientCredits/index.js index 6335b49ee..1b65245ac 100644 --- a/ui/component/claimInsufficientCredits/index.js +++ b/ui/component/claimInsufficientCredits/index.js @@ -1,9 +1,11 @@ import { connect } from 'react-redux'; import { makeSelectInsufficientCreditsForUri } from 'redux/selectors/content'; +import { makeSelectClaimWasPurchased } from 'lbry-redux'; import ClaimInsufficientCredits from './view'; const select = (state, props) => ({ isInsufficientCredits: makeSelectInsufficientCreditsForUri(props.uri)(state), + claimWasPurchased: makeSelectClaimWasPurchased(props.uri)(state), }); export default connect(select)(ClaimInsufficientCredits); diff --git a/ui/component/claimInsufficientCredits/view.jsx b/ui/component/claimInsufficientCredits/view.jsx index 28d50fef1..6d7d33fc2 100644 --- a/ui/component/claimInsufficientCredits/view.jsx +++ b/ui/component/claimInsufficientCredits/view.jsx @@ -7,12 +7,13 @@ type Props = { uri: string, fileInfo: FileListItem, isInsufficientCredits: boolean, + claimWasPurchased: boolea, }; function ClaimInsufficientCredits(props: Props) { - const { isInsufficientCredits, fileInfo } = props; + const { isInsufficientCredits, fileInfo, claimWasPurchased } = props; - if (fileInfo || !isInsufficientCredits) { + if (fileInfo || !isInsufficientCredits || claimWasPurchased) { return null; } diff --git a/ui/component/claimListDiscover/view.jsx b/ui/component/claimListDiscover/view.jsx index 8ac3dbeb4..655ad03e6 100644 --- a/ui/component/claimListDiscover/view.jsx +++ b/ui/component/claimListDiscover/view.jsx @@ -55,6 +55,7 @@ type Props = { followedTags?: Array, injectedItem: ?Node, infiniteScroll?: Boolean, + feeAmount?: string, }; function ClaimListDiscover(props: Props) { @@ -92,6 +93,7 @@ function ClaimListDiscover(props: Props) { infiniteScroll = true, followedTags, injectedItem, + feeAmount, } = props; const didNavigateForward = history.action === 'PUSH'; const { search } = location; @@ -113,14 +115,17 @@ function ClaimListDiscover(props: Props) { const streamTypeParam = streamType || (CS.FILE_TYPES.includes(contentTypeParam) && contentTypeParam) || defaultStreamType || null; const durationParam = urlParams.get(CS.DURATION_KEY) || null; - + const channelIdsInUrl = urlParams.get(CS.CHANNEL_IDS_KEY); + const channelIdsParam = channelIdsInUrl ? channelIdsInUrl.split(',') : channelIds; + const feeAmountParam = urlParams.get('fee_amount') || feeAmount || CS.FEE_AMOUNT_ANY; const showDuration = !(claimType && claimType === CS.CLAIM_CHANNEL); const isFiltered = () => Boolean( urlParams.get(CS.FRESH_KEY) || urlParams.get(CS.CONTENT_KEY) || urlParams.get(CS.DURATION_KEY) || - urlParams.get(CS.TAGS_KEY) + urlParams.get(CS.TAGS_KEY) || + urlParams.get(CS.FEE_AMOUNT_KEY) ); useEffect(() => { @@ -143,6 +148,7 @@ function ClaimListDiscover(props: Props) { duration?: string, reposted_claim_id?: string, stream_types?: any, + fee_amount?: string, } = { page_size: pageSize || CS.PAGE_SIZE, page, @@ -151,10 +157,10 @@ function ClaimListDiscover(props: Props) { // no_totals makes it so the sdk doesn't have to calculate total number pages for pagination // it's faster, but we will need to remove it if we start using total_pages no_totals: true, - channel_ids: channelIds || [], + channel_ids: channelIdsParam || [], not_channel_ids: - // If channelIds were passed in, we don't need not_channel_ids - !channelIds && hiddenUris && hiddenUris.length ? hiddenUris.map(hiddenUri => hiddenUri.split('#')[1]) : [], + // If channelIdsParam were passed in, we don't need not_channel_ids + !channelIdsParam && hiddenUris && hiddenUris.length ? hiddenUris.map(hiddenUri => hiddenUri.split('#')[1]) : [], not_tags: !showNsfw ? MATURE_TAGS : [], order_by: orderParam === CS.ORDER_BY_TRENDING @@ -212,6 +218,10 @@ function ClaimListDiscover(props: Props) { } } + if (feeAmountParam) { + options.fee_amount = feeAmountParam; + } + if (durationParam) { if (durationParam === CS.DURATION_SHORT) { options.duration = '<=1800'; @@ -310,6 +320,15 @@ function ClaimListDiscover(props: Props) { history.push(url); } + function handleAdvancedReset() { + const newUrlParams = new URLSearchParams(search); + newUrlParams.delete('claim_type'); + newUrlParams.delete('channel_ids'); + const newSearch = `?${newUrlParams.toString()}`; + + history.push(newSearch); + } + function getParamFromTags(t) { if (t === CS.TAGS_ALL || t === CS.TAGS_FOLLOWED) { return t; @@ -319,7 +338,7 @@ function ClaimListDiscover(props: Props) { } function buildUrl(delta) { - const newUrlParams = new URLSearchParams(); + const newUrlParams = new URLSearchParams(location.search); CS.KEYS.forEach(k => { // $FlowFixMe append() can't take null as second arg, but get() can return null if (urlParams.get(k) !== null) newUrlParams.append(k, urlParams.get(k)); @@ -370,6 +389,13 @@ function ClaimListDiscover(props: Props) { newUrlParams.set(CS.TAGS_KEY, delta.value); } break; + case CS.FEE_AMOUNT_KEY: + if (delta.value === CS.FEE_AMOUNT_ANY) { + newUrlParams.delete(CS.FEE_AMOUNT_KEY); + } else { + newUrlParams.set(CS.FEE_AMOUNT_KEY, delta.value); + } + break; } return `?${newUrlParams.toString()}`; } @@ -485,7 +511,7 @@ function ClaimListDiscover(props: Props) { } > {CS.CONTENT_TYPES.map(type => { - if (type !== CS.CLAIM_CHANNEL || (type === CS.CLAIM_CHANNEL && !channelIds)) { + if (type !== CS.CLAIM_CHANNEL || (type === CS.CLAIM_CHANNEL && !channelIdsParam)) { return (