diff --git a/dist/bundle.es.js b/dist/bundle.es.js index 8bb5ace..87cf4e4 100644 --- a/dist/bundle.es.js +++ b/dist/bundle.es.js @@ -1278,7 +1278,7 @@ const makeSelectMetadataItemForUri = (uri, key) => reselect.createSelector(makeS const makeSelectTitleForUri = uri => reselect.createSelector(makeSelectMetadataForUri(uri), metadata => metadata && metadata.title); const makeSelectDateForUri = uri => reselect.createSelector(makeSelectClaimForUri(uri), claim => { - const timestamp = claim && claim.timestamp ? claim.timestamp * 1000 : undefined; + const timestamp = claim && claim.value && (claim.value.release_time ? claim.value.release_time * 1000 : claim.meta.creation_timestamp * 1000); if (!timestamp) { return undefined; } @@ -1977,20 +1977,33 @@ function doResolveUris(uris, returnCachedClaims = false) { lbryProxy.resolve({ urls: urisToResolve }).then(result => { Object.entries(result).forEach(([uri, uriResolveInfo]) => { const fallbackResolveInfo = { - claim: null, + stream: null, claimsInChannel: null, - certificate: null + channel: null }; // Flow has terrible Object.entries support // https://github.com/facebook/flow/issues/2221 - // $FlowFixMe - if (uriResolveInfo.error) { - resolveInfo[uri] = _extends$3({}, fallbackResolveInfo); - } else { - // $FlowFixMe - const { claim, certificate, claims_in_channel: claimsInChannel } = uriResolveInfo; - resolveInfo[uri] = { claim, certificate, claimsInChannel }; + if (uriResolveInfo) { + if (uriResolveInfo.error) { + resolveInfo[uri] = _extends$3({}, fallbackResolveInfo); + } else { + let result = {}; + if (uriResolveInfo.value_type === 'channel') { + result.channel = uriResolveInfo; + // $FlowFixMe + result.claimsInChannel = uriResolveInfo.meta.claims_in_channel; + } else { + result.stream = uriResolveInfo; + if (uriResolveInfo.signing_channel) { + result.channel = uriResolveInfo.signing_channel; + result.claimsInChannel = uriResolveInfo.signing_channel.meta.claims_in_channel; + } + } + + // $FlowFixMe + resolveInfo[uri] = result; + } } }); @@ -2104,7 +2117,7 @@ function doFetchClaimsByChannel(uri, page = 1) { data: { uri, page } }); - lbryProxy.claim_search({ channel_name: uri, page: page || 1, winning: true }).then(result => { + lbryProxy.claim_search({ channel: uri, is_controlling: true, page: page || 1, order_by: ['release_time'] }).then(result => { const { items: claimsInChannel, page: returnedPage } = result; dispatch({ @@ -2270,10 +2283,12 @@ const selectSearchDownloadUris = query => reselect.createSelector(selectFileInfo return; } - const titleParts = title.toLowerCase().split(' '); - if (arrayContainsQueryPart(titleParts)) { - downloadResultsFromQuery.push(fileInfo); - return; + if (title) { + const titleParts = title.toLowerCase().split(' '); + if (arrayContainsQueryPart(titleParts)) { + downloadResultsFromQuery.push(fileInfo); + return; + } } if (author) { @@ -2706,34 +2721,36 @@ const defaultState = { }; reducers[RESOLVE_URIS_COMPLETED] = (state, action) => { - const { resolveInfo } = action.data; + const { + resolveInfo + } = action.data; const byUri = Object.assign({}, state.claimsByUri); const byId = Object.assign({}, state.byId); const channelClaimCounts = Object.assign({}, state.channelClaimCounts); Object.entries(resolveInfo).forEach(([uri, resolveResponse]) => { // $FlowFixMe - if (resolveResponse.certificate && !Number.isNaN(resolveResponse.claimsInChannel)) { + if (resolveResponse.claimsInChannel) { // $FlowFixMe channelClaimCounts[uri] = resolveResponse.claimsInChannel; } }); // $FlowFixMe - Object.entries(resolveInfo).forEach(([uri, { certificate, claim }]) => { - if (claim && !certificate) { - byId[claim.claim_id] = claim; - byUri[uri] = claim.claim_id; - } else if (claim && certificate) { - byId[claim.claim_id] = claim; - byUri[uri] = claim.claim_id; + Object.entries(resolveInfo).forEach(([uri, { channel, stream }]) => { + if (stream && !channel) { + byId[stream.claim_id] = stream; + byUri[uri] = stream.claim_id; + } else if (stream && channel) { + byId[stream.claim_id] = stream; + byUri[uri] = stream.claim_id; - byId[certificate.claim_id] = certificate; - const channelUri = `lbry://${certificate.name}#${certificate.claim_id}`; - byUri[channelUri] = certificate.claim_id; - } else if (!claim && certificate) { - byId[certificate.claim_id] = certificate; - byUri[uri] = certificate.claim_id; + byId[channel.claim_id] = channel; + const channelUri = channel.permanent_url; + byUri[channelUri] = channel.claim_id; + } else if (!stream && channel) { + byId[channel.claim_id] = channel; + byUri[uri] = channel.claim_id; } else { byUri[uri] = null; } @@ -3164,16 +3181,6 @@ reducers$2[LOADING_VIDEO_FAILED] = (state, action) => { }); }; -reducers$2[FETCH_DATE] = (state, action) => { - const { time } = action.data; - if (time) { - return Object.assign({}, state, { - publishedDate: time - }); - } - return null; -}; - reducers$2[SET_FILE_LIST_SORT] = (state, action) => { const pageSortStates = { [PUBLISHED]: 'fileListPublishedSort', diff --git a/dist/flow-typed/Claim.js b/dist/flow-typed/Claim.js index 69ac31b..e8744f5 100644 --- a/dist/flow-typed/Claim.js +++ b/dist/flow-typed/Claim.js @@ -1,49 +1,52 @@ // @flow -declare type ClaimWithPossibleCertificate = { - certificate?: ChannelClaim, - claim: StreamClaim, -}; +declare type Claim = StreamClaim | ChannelClaim; declare type ChannelClaim = GenericClaim & { + is_channel_signature_valid?: boolean, // we may have signed channels in the future, fixes some flow issues for now. + signing_channel?: ChannelMetadata, value: ChannelMetadata, }; declare type StreamClaim = GenericClaim & { is_channel_signature_valid?: boolean, - signing_channel?: { - claim_id: string, - name: string, - value: { - public_key: string, - }, - }, + signing_channel?: ChannelMetadata, value: StreamMetadata, }; declare type GenericClaim = { address: string, // address associated with tx - amount: number, // bid amount at time of tx + amount: string, // bid amount at time of tx + canonical_url: string, // URL with short id, includes channel with short id claim_id: string, // unique claim identifier - claim_sequence: number, + claim_sequence: number, // not being used currently claim_op: 'create' | 'update', - confirmations: number, // This isn't the most stable atm: https://github.com/lbryio/lbry/issues/2000 - decoded_claim: boolean, // claim made in accordance with sdk protobuf types - effective_amount: number, // bid amount + supports - timestamp?: number, // date of transaction - has_signature: boolean, + confirmations: number, + decoded_claim: boolean, // Not available currently https://github.com/lbryio/lbry/issues/2044 + timestamp?: number, // date of last transaction height: number, // block height the tx was confirmed - hex: string, // `value` hex encoded name: string, - channel_name?: string, normalized_name: string, // `name` normalized via unicode NFD spec, nout: number, // index number for an output of a tx permanent_url: string, // name + claim_id - supports: Array<{}>, // TODO: add support type once we start using it + short_url: string, // permanent_url with short id, no channel txid: string, // unique tx id type: 'claim' | 'update' | 'support', - valid_at_height?: number, // BUG: this should always exist https://github.com/lbryio/lbry/issues/1728 value_type: 'stream' | 'channel', + meta: { + activation_height: number, + claims_in_channel?: number, + creation_height: number, + creation_timestamp: number, + effective_amount: string, + expiration_height: number, + is_controlling: boolean, + support_amount: string, + trending_global: number, + trending_group: number, + trending_local: number, + trending_mixed: number, + }, }; declare type GenericMetadata = { @@ -59,6 +62,7 @@ declare type GenericMetadata = { declare type ChannelMetadata = GenericMetadata & { public_key: string, + public_key_id: string, cover_url?: string, email?: string, website_url?: string, diff --git a/dist/flow-typed/Lbry.js b/dist/flow-typed/Lbry.js index e4d9090..d67a17d 100644 --- a/dist/flow-typed/Lbry.js +++ b/dist/flow-typed/Lbry.js @@ -66,8 +66,8 @@ declare type VersionResponse = { declare type ResolveResponse = { // Keys are the url(s) passed to resolve [string]: - | { error: {}, certificate: ChannelClaim, claims_in_channel: number } - | { error?: {}, claim: StreamClaim, certificate?: ChannelClaim }, + | Claim + | { error?: {} }, }; declare type GetResponse = FileListItem; @@ -86,18 +86,19 @@ declare type GenericTxResponse = { declare type PublishResponse = GenericTxResponse & { // Only first value in outputs is a claim // That's the only value we care about - outputs: Array, + outputs: Array, }; declare type ClaimSearchResponse = { - items: Array, + items: Array, page: number, page_size: number, - page_number: number, + total_items: number, + total_pages: number, }; declare type ClaimListResponse = { - claims: Array, + claims: Array, }; declare type ChannelCreateResponse = GenericTxResponse & { diff --git a/flow-typed/Claim.js b/flow-typed/Claim.js index 69ac31b..f18b128 100644 --- a/flow-typed/Claim.js +++ b/flow-typed/Claim.js @@ -1,49 +1,52 @@ // @flow -declare type ClaimWithPossibleCertificate = { - certificate?: ChannelClaim, - claim: StreamClaim, -}; +declare type Claim = StreamClaim | ChannelClaim; declare type ChannelClaim = GenericClaim & { + is_channel_signature_valid?: boolean, // we may have signed channels in the future, fixes some flow issues for now. + signing_channel?: ChannelClaim, value: ChannelMetadata, }; declare type StreamClaim = GenericClaim & { is_channel_signature_valid?: boolean, - signing_channel?: { - claim_id: string, - name: string, - value: { - public_key: string, - }, - }, + signing_channel?: ChannelClaim, value: StreamMetadata, }; declare type GenericClaim = { address: string, // address associated with tx - amount: number, // bid amount at time of tx + amount: string, // bid amount at time of tx + canonical_url: string, // URL with short id, includes channel with short id claim_id: string, // unique claim identifier - claim_sequence: number, + claim_sequence: number, // not being used currently claim_op: 'create' | 'update', - confirmations: number, // This isn't the most stable atm: https://github.com/lbryio/lbry/issues/2000 - decoded_claim: boolean, // claim made in accordance with sdk protobuf types - effective_amount: number, // bid amount + supports - timestamp?: number, // date of transaction - has_signature: boolean, + confirmations: number, + decoded_claim: boolean, // Not available currently https://github.com/lbryio/lbry/issues/2044 + timestamp?: number, // date of last transaction height: number, // block height the tx was confirmed - hex: string, // `value` hex encoded name: string, - channel_name?: string, normalized_name: string, // `name` normalized via unicode NFD spec, nout: number, // index number for an output of a tx permanent_url: string, // name + claim_id - supports: Array<{}>, // TODO: add support type once we start using it + short_url: string, // permanent_url with short id, no channel txid: string, // unique tx id type: 'claim' | 'update' | 'support', - valid_at_height?: number, // BUG: this should always exist https://github.com/lbryio/lbry/issues/1728 value_type: 'stream' | 'channel', + meta: { + activation_height: number, + claims_in_channel?: number, + creation_height: number, + creation_timestamp: number, + effective_amount: string, + expiration_height: number, + is_controlling: boolean, + support_amount: string, + trending_global: number, + trending_group: number, + trending_local: number, + trending_mixed: number, + }, }; declare type GenericMetadata = { @@ -59,6 +62,7 @@ declare type GenericMetadata = { declare type ChannelMetadata = GenericMetadata & { public_key: string, + public_key_id: string, cover_url?: string, email?: string, website_url?: string, diff --git a/flow-typed/Lbry.js b/flow-typed/Lbry.js index e4d9090..d67a17d 100644 --- a/flow-typed/Lbry.js +++ b/flow-typed/Lbry.js @@ -66,8 +66,8 @@ declare type VersionResponse = { declare type ResolveResponse = { // Keys are the url(s) passed to resolve [string]: - | { error: {}, certificate: ChannelClaim, claims_in_channel: number } - | { error?: {}, claim: StreamClaim, certificate?: ChannelClaim }, + | Claim + | { error?: {} }, }; declare type GetResponse = FileListItem; @@ -86,18 +86,19 @@ declare type GenericTxResponse = { declare type PublishResponse = GenericTxResponse & { // Only first value in outputs is a claim // That's the only value we care about - outputs: Array, + outputs: Array, }; declare type ClaimSearchResponse = { - items: Array, + items: Array, page: number, page_size: number, - page_number: number, + total_items: number, + total_pages: number, }; declare type ClaimListResponse = { - claims: Array, + claims: Array, }; declare type ChannelCreateResponse = GenericTxResponse & { diff --git a/src/redux/actions/claims.js b/src/redux/actions/claims.js index 33dd119..3cbffcd 100644 --- a/src/redux/actions/claims.js +++ b/src/redux/actions/claims.js @@ -34,8 +34,8 @@ export function doResolveUris(uris: Array, returnCachedClaims: boolean = const resolveInfo: { [string]: { - claim: ?StreamClaim, - certificate: ?ChannelClaim, + stream: ?StreamClaim, + channel: ?ChannelClaim, claimsInChannel: ?number, }, } = {}; @@ -43,20 +43,34 @@ export function doResolveUris(uris: Array, returnCachedClaims: boolean = Lbry.resolve({ urls: urisToResolve }).then((result: ResolveResponse) => { Object.entries(result).forEach(([uri, uriResolveInfo]) => { const fallbackResolveInfo = { - claim: null, + stream: null, claimsInChannel: null, - certificate: null, + channel: null, }; // Flow has terrible Object.entries support // https://github.com/facebook/flow/issues/2221 - // $FlowFixMe - if (uriResolveInfo.error) { - resolveInfo[uri] = { ...fallbackResolveInfo }; - } else { - // $FlowFixMe - const { claim, certificate, claims_in_channel: claimsInChannel } = uriResolveInfo; - resolveInfo[uri] = { claim, certificate, claimsInChannel }; + if (uriResolveInfo) { + if (uriResolveInfo.error) { + resolveInfo[uri] = { ...fallbackResolveInfo }; + } else { + let result = {}; + if (uriResolveInfo.value_type === 'channel') { + result.channel = uriResolveInfo; + // $FlowFixMe + result.claimsInChannel = uriResolveInfo.meta.claims_in_channel; + } else { + result.stream = uriResolveInfo; + if (uriResolveInfo.signing_channel) { + result.channel = uriResolveInfo.signing_channel; + result.claimsInChannel = + (uriResolveInfo.meta && uriResolveInfo.meta.claims_in_channel) || 0; + } + } + + // $FlowFixMe + resolveInfo[uri] = result; + } } }); @@ -94,7 +108,7 @@ export function doAbandonClaim(txid: string, nout: number) { return (dispatch: Dispatch, getState: GetState) => { const state = getState(); - const myClaims: Array = selectMyClaimsRaw(state); + const myClaims: Array = selectMyClaimsRaw(state); const mySupports: { [string]: Support } = selectSupportsByOutpoint(state); // A user could be trying to abandon a support or one of their claims @@ -182,20 +196,23 @@ export function doFetchClaimsByChannel(uri: string, page: number = 1) { data: { uri, page }, }); - Lbry.claim_search({ channel_name: uri, page: page || 1, winning: true }).then( - (result: ClaimSearchResponse) => { - const { items: claimsInChannel, page: returnedPage } = result; + Lbry.claim_search({ + channel: uri, + is_controlling: true, + page: page || 1, + order_by: ['release_time'], + }).then((result: ClaimSearchResponse) => { + const { items: claimsInChannel, page: returnedPage } = result; - dispatch({ - type: ACTIONS.FETCH_CHANNEL_CLAIMS_COMPLETED, - data: { - uri, - claims: claimsInChannel || [], - page: returnedPage || undefined, - }, - }); - } - ); + dispatch({ + type: ACTIONS.FETCH_CHANNEL_CLAIMS_COMPLETED, + data: { + uri, + claims: claimsInChannel || [], + page: returnedPage || undefined, + }, + }); + }); }; } diff --git a/src/redux/reducers/claims.js b/src/redux/reducers/claims.js index b4a81e9..cd50cd6 100644 --- a/src/redux/reducers/claims.js +++ b/src/redux/reducers/claims.js @@ -14,9 +14,9 @@ import { buildURI, parseURI } from 'lbryURI'; type State = { channelClaimCounts: { [string]: number }, claimsByUri: { [string]: string }, - byId: { [string]: StreamClaim | ChannelClaim }, + byId: { [string]: Claim }, resolvingUris: Array, - pendingById: { [string]: StreamClaim | ChannelClaim }, + pendingById: { [string]: Claim }, myChannelClaims: Set, abandoningById: { [string]: boolean }, fetchingChannelClaims: { [string]: number }, @@ -46,37 +46,38 @@ const defaultState = { }; reducers[ACTIONS.RESOLVE_URIS_COMPLETED] = (state: State, action: any): State => { - const { resolveInfo }: { [string]: ClaimWithPossibleCertificate } = action.data; + const { + resolveInfo, + }: { + [string]: { + stream: ?StreamClaim, + channel: ?ChannelClaim, + claimsInChannel: ?number, + }, + } = action.data; const byUri = Object.assign({}, state.claimsByUri); const byId = Object.assign({}, state.byId); const channelClaimCounts = Object.assign({}, state.channelClaimCounts); - Object.entries(resolveInfo).forEach( - ([uri: string, resolveResponse: ClaimWithPossibleCertificate]) => { + Object.entries(resolveInfo).forEach(([uri: string, resolveResponse: Claim]) => { + // $FlowFixMe + if (resolveResponse.claimsInChannel) { // $FlowFixMe - if (resolveResponse.certificate && !Number.isNaN(resolveResponse.claimsInChannel)) { - // $FlowFixMe - channelClaimCounts[uri] = resolveResponse.claimsInChannel; - } + channelClaimCounts[uri] = resolveResponse.claimsInChannel; } - ); + }); // $FlowFixMe - Object.entries(resolveInfo).forEach(([uri, { certificate, claim }]) => { - if (claim && !certificate) { - byId[claim.claim_id] = claim; - byUri[uri] = claim.claim_id; - } else if (claim && certificate) { - byId[claim.claim_id] = claim; - byUri[uri] = claim.claim_id; - - byId[certificate.claim_id] = certificate; - const channelUri = `lbry://${certificate.name}#${certificate.claim_id}`; - byUri[channelUri] = certificate.claim_id; - } else if (!claim && certificate) { - byId[certificate.claim_id] = certificate; - byUri[uri] = certificate.claim_id; - } else { + Object.entries(resolveInfo).forEach(([uri, { channel, stream }]) => { + if (stream) { + byId[stream.claim_id] = stream; + byUri[uri] = stream.claim_id; + } + if (channel) { + byId[channel.claim_id] = channel; + byUri[stream ? channel.permanent_url : uri] = channel.claim_id; + } + if (!stream && !channel) { byUri[uri] = null; } }); @@ -95,15 +96,12 @@ reducers[ACTIONS.FETCH_CLAIM_LIST_MINE_STARTED] = (state: State): State => }); reducers[ACTIONS.FETCH_CLAIM_LIST_MINE_COMPLETED] = (state: State, action: any): State => { - const { claims }: { claims: Array } = action.data; + const { claims }: { claims: Array } = action.data; const byId = Object.assign({}, state.byId); const byUri = Object.assign({}, state.claimsByUri); - const pendingById: { [string]: StreamClaim | ChannelClaim } = Object.assign( - {}, - state.pendingById - ); + const pendingById: { [string]: Claim } = Object.assign({}, state.pendingById); - claims.forEach((claim: StreamClaim | ChannelClaim) => { + claims.forEach((claim: Claim) => { const uri = buildURI({ claimName: claim.name, claimId: claim.claim_id }); if (claim.type && claim.type.match(/claim|update/)) { diff --git a/src/redux/reducers/file_info.js b/src/redux/reducers/file_info.js index 1d9f950..dbc5e86 100644 --- a/src/redux/reducers/file_info.js +++ b/src/redux/reducers/file_info.js @@ -161,16 +161,6 @@ reducers[ACTIONS.LOADING_VIDEO_FAILED] = (state, action) => { }); }; -reducers[ACTIONS.FETCH_DATE] = (state, action) => { - const { time } = action.data; - if (time) { - return Object.assign({}, state, { - publishedDate: time, - }); - } - return null; -}; - reducers[ACTIONS.SET_FILE_LIST_SORT] = (state, action) => { const pageSortStates = { [PAGES.PUBLISHED]: 'fileListPublishedSort', diff --git a/src/redux/selectors/claims.js b/src/redux/selectors/claims.js index 7a1808f..0cf4bdf 100644 --- a/src/redux/selectors/claims.js +++ b/src/redux/selectors/claims.js @@ -190,7 +190,12 @@ export const makeSelectDateForUri = (uri: string) => createSelector( makeSelectClaimForUri(uri), claim => { - const timestamp = claim && claim.timestamp ? claim.timestamp * 1000 : undefined; + const timestamp = + claim && + claim.value && + (claim.value.release_time + ? claim.value.release_time * 1000 + : claim.meta.creation_timestamp * 1000); if (!timestamp) { return undefined; } @@ -368,7 +373,7 @@ export const makeSelectClaimIsNsfw = (uri: string): boolean => // Or possibly come from users settings of what tags they want to hide // For now, there is just a hard coded list of tags inside `isClaimNsfw` // selectNaughtyTags(), - (claim: StreamClaim) => { + (claim: Claim) => { if (!claim) { return false; } diff --git a/src/redux/selectors/file_info.js b/src/redux/selectors/file_info.js index ab941ea..4718cd8 100644 --- a/src/redux/selectors/file_info.js +++ b/src/redux/selectors/file_info.js @@ -164,10 +164,12 @@ export const selectSearchDownloadUris = query => return; } - const titleParts = title.toLowerCase().split(' '); - if (arrayContainsQueryPart(titleParts)) { - downloadResultsFromQuery.push(fileInfo); - return; + if (title) { + const titleParts = title.toLowerCase().split(' '); + if (arrayContainsQueryPart(titleParts)) { + downloadResultsFromQuery.push(fileInfo); + return; + } } if (author) { diff --git a/src/util/claim.js b/src/util/claim.js index 0e56ce3..73adb7a 100644 --- a/src/util/claim.js +++ b/src/util/claim.js @@ -5,7 +5,7 @@ const naughtyTags = ['porn', 'nsfw', 'mature', 'xxx'].reduce( {} ); -export const isClaimNsfw = (claim: StreamClaim): boolean => { +export const isClaimNsfw = (claim: Claim): boolean => { if (!claim) { throw new Error('No claim passed to isClaimNsfw()'); }