diff --git a/dist/bundle.es.js b/dist/bundle.es.js index 72d93c5..543bc0f 100644 --- a/dist/bundle.es.js +++ b/dist/bundle.es.js @@ -1473,7 +1473,7 @@ const channelNameMinLength = 1; const claimIdMaxLength = 40; // see https://spec.lbry.com/#urls -const regexInvalidURI = /[ =&#:$@%?;/\\"<>%\{\}|^~[\]`\u{0000}-\u{0008}\u{000b}-\u{000c}\u{000e}-\u{001F}\u{D800}-\u{DFFF}\u{FFFE}-\u{FFFF}]/u; +const regexInvalidURI = /[ =&#:$@%?;/\\"<>%{}|^~[\]`\u{0000}-\u{0008}\u{000b}-\u{000c}\u{000e}-\u{001F}\u{D800}-\u{DFFF}\u{FFFE}-\u{FFFF}]/u; const regexAddress = /^(b|r)(?=[^0OIl]{32,33})[0-9A-Za-z]{32,33}$/; const regexPartProtocol = '^((?:lbry://)?)'; const regexPartStreamOrChannelName = '([^:$#/]*)'; @@ -1481,6 +1481,11 @@ const regexPartModifierSeparator = '([:$#]?)([^/]*)'; const queryStringBreaker = '^([\\S]+)([?][\\S]*)'; const separateQuerystring = new RegExp(queryStringBreaker); +const MOD_SEQUENCE_SEPARATOR = '*'; +const MOD_CLAIM_ID_SEPARATOR_OLD = '#'; +const MOD_CLAIM_ID_SEPARATOR = ':'; +const MOD_BID_POSITION_SEPARATOR = '$'; + /** * Parses a LBRY name into its component parts. Throws errors with user-friendly * messages for invalid names. @@ -1582,11 +1587,11 @@ function parseURIModifier(modSeperator, modValue) { throw new Error(__(`No modifier provided after separator %modSeperator%.`, { modSeperator })); } - if (modSeperator === '#') { + if (modSeperator === MOD_CLAIM_ID_SEPARATOR || MOD_CLAIM_ID_SEPARATOR_OLD) { claimId = modValue; - } else if (modSeperator === ':') { + } else if (modSeperator === MOD_SEQUENCE_SEPARATOR) { claimSequence = modValue; - } else if (modSeperator === '$') { + } else if (modSeperator === MOD_BID_POSITION_SEPARATOR) { bidPosition = modValue; } } @@ -1717,6 +1722,25 @@ function convertToShareLink(URL) { }, true, 'https://open.lbry.com/'); } +function splitBySeparator(uri) { + const protocolLength = 7; + return uri.startsWith('lbry://') ? uri.slice(protocolLength).split(/[#:*]/) : uri.split(/#:\*\$/); +} + +function isURIEqual(uriA, uriB) { + const parseA = parseURI(normalizeURI(uriA)); + const parseB = parseURI(normalizeURI(uriB)); + if (parseA.isChannel) { + if (parseB.isChannel && parseA.channelClaimId === parseB.channelClaimId) { + return true; + } + } else if (parseA.streamClaimId === parseB.streamClaimId) { + return true; + } else { + return false; + } +} + /* eslint-disable */ // underscore's deep equal function // https://github.com/jashkenas/underscore/blob/master/underscore.js#L1189 @@ -2461,7 +2485,7 @@ const makeSelectClaimForUri = (uri, returnRepost = true) => reselect.createSelec const channelUrl = claim.signing_channel && (claim.signing_channel.canonical_url || claim.signing_channel.permanent_url); return _extends$3({}, repostedClaim, { - repost_url: uri, + repost_url: normalizeURI(uri), repost_channel_url: channelUrl, repost_bid_amount: claim && claim.meta && claim.meta.effective_amount }); @@ -2712,9 +2736,9 @@ const makeSelectPendingClaimForUri = uri => reselect.createSelector(selectPendin return matchingClaim || null; }); -const makeSelectTotalItemsForChannel = uri => reselect.createSelector(selectChannelClaimCounts, byUri => byUri && byUri[uri]); +const makeSelectTotalItemsForChannel = uri => reselect.createSelector(selectChannelClaimCounts, byUri => byUri && byUri[normalizeURI(uri)]); -const makeSelectTotalPagesForChannel = (uri, pageSize = 10) => reselect.createSelector(selectChannelClaimCounts, byUri => byUri && byUri[uri] && Math.ceil(byUri[uri] / pageSize)); +const makeSelectTotalPagesForChannel = (uri, pageSize = 10) => reselect.createSelector(selectChannelClaimCounts, byUri => byUri && byUri[uri] && Math.ceil(byUri[normalizeURI(uri)] / pageSize)); const makeSelectNsfwCountFromUris = uris => reselect.createSelector(selectClaimsByUri, claims => uris.reduce((acc, uri) => { const claim = claims[uri]; @@ -7936,6 +7960,7 @@ exports.formatFullPrice = formatFullPrice; exports.isClaimNsfw = isClaimNsfw; exports.isNameValid = isNameValid; exports.isURIClaimable = isURIClaimable; +exports.isURIEqual = isURIEqual; exports.isURIValid = isURIValid; exports.makeSelectAbandoningClaimById = makeSelectAbandoningClaimById; exports.makeSelectAmountForUri = makeSelectAmountForUri; @@ -8151,5 +8176,6 @@ exports.selectWalletState = selectWalletState; exports.selectWalletUnlockPending = selectWalletUnlockPending; exports.selectWalletUnlockResult = selectWalletUnlockResult; exports.selectWalletUnlockSucceeded = selectWalletUnlockSucceeded; +exports.splitBySeparator = splitBySeparator; exports.toQueryString = toQueryString; exports.walletReducer = walletReducer; diff --git a/src/index.js b/src/index.js index 5d04fc4..cb38ecf 100644 --- a/src/index.js +++ b/src/index.js @@ -52,6 +52,8 @@ export { isURIClaimable, isNameValid, convertToShareLink, + splitBySeparator, + isURIEqual, } from 'lbryURI'; // middlware diff --git a/src/lbryURI.js b/src/lbryURI.js index ee91388..02e13c4 100644 --- a/src/lbryURI.js +++ b/src/lbryURI.js @@ -4,7 +4,7 @@ const channelNameMinLength = 1; const claimIdMaxLength = 40; // see https://spec.lbry.com/#urls -export const regexInvalidURI = /[ =&#:$@%?;/\\"<>%\{\}|^~[\]`\u{0000}-\u{0008}\u{000b}-\u{000c}\u{000e}-\u{001F}\u{D800}-\u{DFFF}\u{FFFE}-\u{FFFF}]/u; +export const regexInvalidURI = /[ =&#:$@%?;/\\"<>%{}|^~[\]`\u{0000}-\u{0008}\u{000b}-\u{000c}\u{000e}-\u{001F}\u{D800}-\u{DFFF}\u{FFFE}-\u{FFFF}]/u; export const regexAddress = /^(b|r)(?=[^0OIl]{32,33})[0-9A-Za-z]{32,33}$/; const regexPartProtocol = '^((?:lbry://)?)'; const regexPartStreamOrChannelName = '([^:$#/]*)'; @@ -12,6 +12,11 @@ const regexPartModifierSeparator = '([:$#]?)([^/]*)'; const queryStringBreaker = '^([\\S]+)([?][\\S]*)'; const separateQuerystring = new RegExp(queryStringBreaker); +const MOD_SEQUENCE_SEPARATOR = '*'; +const MOD_CLAIM_ID_SEPARATOR_OLD = '#'; +const MOD_CLAIM_ID_SEPARATOR = ':'; +const MOD_BID_POSITION_SEPARATOR = '$'; + /** * Parses a LBRY name into its component parts. Throws errors with user-friendly * messages for invalid names. @@ -144,11 +149,11 @@ function parseURIModifier(modSeperator: ?string, modValue: ?string) { throw new Error(__(`No modifier provided after separator %modSeperator%.`, { modSeperator })); } - if (modSeperator === '#') { + if (modSeperator === MOD_CLAIM_ID_SEPARATOR || MOD_CLAIM_ID_SEPARATOR_OLD) { claimId = modValue; - } else if (modSeperator === ':') { + } else if (modSeperator === MOD_SEQUENCE_SEPARATOR) { claimSequence = modValue; - } else if (modSeperator === '$') { + } else if (modSeperator === MOD_BID_POSITION_SEPARATOR) { bidPosition = modValue; } } @@ -320,3 +325,22 @@ export function convertToShareLink(URL: string) { 'https://open.lbry.com/' ); } + +export function splitBySeparator(uri: string) { + const protocolLength = 7; + return uri.startsWith('lbry://') ? uri.slice(protocolLength).split(/[#:*]/) : uri.split(/#:\*\$/); +} + +export function isURIEqual(uriA: string, uriB: string) { + const parseA = parseURI(normalizeURI(uriA)); + const parseB = parseURI(normalizeURI(uriB)); + if (parseA.isChannel) { + if (parseB.isChannel && parseA.channelClaimId === parseB.channelClaimId) { + return true; + } + } else if (parseA.streamClaimId === parseB.streamClaimId) { + return true; + } else { + return false; + } +} diff --git a/src/redux/selectors/claims.js b/src/redux/selectors/claims.js index 2071913..f5a03ed 100644 --- a/src/redux/selectors/claims.js +++ b/src/redux/selectors/claims.js @@ -165,7 +165,7 @@ export const makeSelectClaimForUri = (uri: string, returnRepost: boolean = true) return { ...repostedClaim, - repost_url: uri, + repost_url: normalizeURI(uri), repost_channel_url: channelUrl, repost_bid_amount: claim && claim.meta && claim.meta.effective_amount, }; @@ -299,8 +299,8 @@ export const makeSelectMyPurchasesForPage = (query: ?string, page: number = 1) = const end = Number(page) * Number(CLAIM.PAGE_SIZE); return matchingFileInfos && matchingFileInfos.length ? matchingFileInfos - .slice(start, end) - .map(fileInfo => fileInfo.canonical_url || fileInfo.permanent_url) + .slice(start, end) + .map(fileInfo => fileInfo.canonical_url || fileInfo.permanent_url) : []; } ); @@ -393,8 +393,8 @@ export const makeSelectDateForUri = (uri: string) => (claim.value.release_time ? claim.value.release_time * 1000 : claim.meta && claim.meta.creation_timestamp - ? claim.meta.creation_timestamp * 1000 - : null); + ? claim.meta.creation_timestamp * 1000 + : null); if (!timestamp) { return undefined; } @@ -630,13 +630,13 @@ export const makeSelectPendingClaimForUri = (uri: string) => export const makeSelectTotalItemsForChannel = (uri: string) => createSelector( selectChannelClaimCounts, - byUri => byUri && byUri[uri] + byUri => byUri && byUri[normalizeURI(uri)] ); export const makeSelectTotalPagesForChannel = (uri: string, pageSize: number = 10) => createSelector( selectChannelClaimCounts, - byUri => byUri && byUri[uri] && Math.ceil(byUri[uri] / pageSize) + byUri => byUri && byUri[uri] && Math.ceil(byUri[normalizeURI(uri)] / pageSize) ); export const makeSelectNsfwCountFromUris = (uris: Array) =>