parent
68a4697c7d
commit
68ceb7f440
8 changed files with 78 additions and 32 deletions
2
flow-typed/lbryURI.js
vendored
2
flow-typed/lbryURI.js
vendored
|
@ -13,6 +13,8 @@ declare type LbryUrlObj = {
|
|||
primaryBidPosition?: number,
|
||||
secondaryBidPosition?: number,
|
||||
startTime?: number,
|
||||
queryString?: string,
|
||||
pathHash?: string,
|
||||
|
||||
// Below are considered deprecated and should not be used due to unreliableness with claim.canonical_url
|
||||
claimName?: string,
|
||||
|
|
|
@ -5,7 +5,7 @@ import { lazyImport } from 'util/lazyImport';
|
|||
import { tusUnlockAndNotify, tusHandleTabUpdates } from 'util/tus';
|
||||
import analytics from 'analytics';
|
||||
import { setSearchUserId } from 'redux/actions/search';
|
||||
import { normalizeURI } from 'util/lbryURI';
|
||||
import { parseURI, buildURI } from 'util/lbryURI';
|
||||
import { generateGoogleCacheUrl } from 'util/url';
|
||||
import Router from 'component/router/index';
|
||||
import ModalRouter from 'modal/modalRouter';
|
||||
|
@ -187,7 +187,10 @@ function App(props: Props) {
|
|||
|
||||
let uri;
|
||||
try {
|
||||
uri = normalizeURI(path);
|
||||
// here queryString and startTime are "removed" from the buildURI process
|
||||
// to build only the uri itself
|
||||
const { queryString, startTime, ...parsedUri } = parseURI(path);
|
||||
uri = buildURI({ ...parsedUri });
|
||||
} catch (e) {
|
||||
const match = path.match(/[#/:]/);
|
||||
|
||||
|
|
|
@ -64,7 +64,7 @@ function Page(props: Props) {
|
|||
} = props;
|
||||
|
||||
const {
|
||||
location: { pathname },
|
||||
location: { pathname, hash },
|
||||
} = useHistory();
|
||||
|
||||
const theaterMode = renderMode === 'video' || renderMode === 'audio' ? videoTheaterMode : false;
|
||||
|
@ -73,11 +73,10 @@ function Page(props: Props) {
|
|||
const isLandscapeRotated = useIsMobileLandscape();
|
||||
const [sidebarOpen, setSidebarOpen] = usePersistedState('sidebar', false);
|
||||
|
||||
const url = pathname.slice(1).replace(/:/g, '#');
|
||||
const urlPath = `lbry://${(pathname + hash).slice(1).replace(/:/g, '#')}`;
|
||||
let isOnFilePage = false;
|
||||
try {
|
||||
const url = pathname.slice(1).replace(/:/g, '#');
|
||||
const { isChannel } = parseURI(url);
|
||||
const { isChannel } = parseURI(urlPath);
|
||||
|
||||
if (!isChannel) isOnFilePage = true;
|
||||
} catch (e) {}
|
||||
|
@ -93,7 +92,7 @@ function Page(props: Props) {
|
|||
|
||||
return (
|
||||
<>
|
||||
<Wallpaper uri={url} />
|
||||
<Wallpaper uri={urlPath} />
|
||||
{!noHeader && (
|
||||
<Header
|
||||
authHeader={authPage}
|
||||
|
|
|
@ -31,18 +31,26 @@ import { doClaimEligiblePurchaseRewards } from 'redux/actions/rewards';
|
|||
import { selectDaemonSettings, selectClientSetting, selectHomepageData } from 'redux/selectors/settings';
|
||||
import { toggleVideoTheaterMode, toggleAutoplayNext, doSetClientSetting } from 'redux/actions/settings';
|
||||
import { selectUserVerifiedEmail, selectUser } from 'redux/selectors/user';
|
||||
import { parseURI } from 'util/lbryURI';
|
||||
import { doToast } from 'redux/actions/notifications';
|
||||
|
||||
const select = (state, props) => {
|
||||
const { search } = props.location;
|
||||
const { search, pathname, hash } = props.location;
|
||||
const urlParams = new URLSearchParams(search);
|
||||
const autoplay = urlParams.get('autoplay');
|
||||
const uri = props.uri;
|
||||
|
||||
const urlPath = `lbry://${(pathname + hash).slice(1)}`;
|
||||
let startTime;
|
||||
try {
|
||||
({ startTime } = parseURI(urlPath));
|
||||
} catch (e) {}
|
||||
|
||||
const claim = selectClaimForUri(state, uri);
|
||||
|
||||
// TODO: eventually this should be received from DB and not local state (https://github.com/lbryio/lbry-desktop/issues/6796)
|
||||
const position = urlParams.get('t') !== null ? urlParams.get('t') : selectContentPositionForUri(state, uri);
|
||||
const position =
|
||||
startTime || (urlParams.get('t') !== null ? urlParams.get('t') : selectContentPositionForUri(state, uri));
|
||||
const userId = selectUser(state) && selectUser(state).id;
|
||||
const internalFeature = selectUser(state) && selectUser(state).internal_feature;
|
||||
const playingUri = selectPlayingUri(state);
|
||||
|
|
|
@ -137,29 +137,37 @@ export default function ShowPage(props: Props) {
|
|||
|
||||
useEffect(() => {
|
||||
if (canonicalUrl) {
|
||||
const urlPath = pathname + hash;
|
||||
const fullParams =
|
||||
urlPath.indexOf('?') > 0 ? urlPath.substring(urlPath.indexOf('?')) : search.length > 0 ? search : '';
|
||||
const canonicalUrlPath = '/' + canonicalUrl.replace(/^lbry:\/\//, '').replace(/#/g, ':') + fullParams;
|
||||
const statePos =
|
||||
hash.indexOf('#state') > -1
|
||||
? hash.indexOf('#state')
|
||||
: hash.indexOf('&state') > -1
|
||||
? hash.indexOf('&state')
|
||||
: undefined;
|
||||
const pageHash = statePos === undefined ? hash : hash.substring(0, statePos);
|
||||
const urlPath = pathname + pageHash;
|
||||
const path = urlPath.slice(1).replace(/:/g, '#');
|
||||
// parseURI can parse queries and hashes when they are mixed with the uri
|
||||
let queryString, pathHash;
|
||||
try {
|
||||
({ queryString, pathHash } = parseURI(path));
|
||||
} catch (e) {}
|
||||
const canonicalUrlPath = '/' + canonicalUrl.replace(/^lbry:\/\//, '').replace(/#/g, ':');
|
||||
|
||||
// replaceState will fail if on a different domain (like webcache.googleusercontent.com)
|
||||
const hostname = isDev ? 'localhost' : DOMAIN;
|
||||
|
||||
if (canonicalUrlPath !== pathname && hostname === window.location.hostname && fullParams !== search) {
|
||||
const urlParams = new URLSearchParams(search);
|
||||
let replaceUrl = canonicalUrlPath;
|
||||
if (canonicalUrlPath !== urlPath && hostname === window.location.hostname) {
|
||||
const urlParams = new URLSearchParams(search || queryString);
|
||||
if (urlParams.get(COLLECTIONS_CONSTS.COLLECTION_ID)) {
|
||||
const listId = urlParams.get(COLLECTIONS_CONSTS.COLLECTION_ID) || '';
|
||||
urlParams.set(COLLECTIONS_CONSTS.COLLECTION_ID, listId);
|
||||
replaceUrl += `?${urlParams.toString()}`;
|
||||
}
|
||||
history.replaceState(history.state, '', replaceUrl);
|
||||
}
|
||||
|
||||
const windowHref = window.location.href;
|
||||
const noUrlParams = search.length === 0;
|
||||
if (windowHref.includes('?') && noUrlParams) {
|
||||
history.replaceState(history.state, '', windowHref.substring(0, windowHref.length - 1));
|
||||
if (urlParams.toString()) replaceUrl += `?${urlParams.toString()}`;
|
||||
if (pathHash || (!pathHash && !queryString && pageHash)) replaceUrl += String(pathHash || pageHash);
|
||||
|
||||
history.replaceState(history.state, '', replaceUrl);
|
||||
}
|
||||
}
|
||||
}, [canonicalUrl, pathname, hash, search]);
|
||||
|
|
|
@ -103,17 +103,18 @@ export function parseURI(url: string, requireProto: boolean = false): LbryUrlObj
|
|||
}
|
||||
|
||||
// Validate and process modifier
|
||||
const [primaryClaimId, primaryClaimSequence, primaryBidPosition] = parseURIModifier(
|
||||
const [primaryClaimId, primaryClaimSequence, primaryBidPosition, primaryPathHash] = parseURIModifier(
|
||||
primaryModSeparator,
|
||||
primaryModValue
|
||||
);
|
||||
const [secondaryClaimId, secondaryClaimSequence, secondaryBidPosition] = parseURIModifier(
|
||||
const [secondaryClaimId, secondaryClaimSequence, secondaryBidPosition, secondaryPathHash] = parseURIModifier(
|
||||
secondaryModSeparator,
|
||||
secondaryModValue
|
||||
);
|
||||
const streamName = includesChannel ? possibleStreamName : streamNameOrChannelName;
|
||||
const streamClaimId = includesChannel ? secondaryClaimId : primaryClaimId;
|
||||
const channelClaimId = includesChannel && primaryClaimId;
|
||||
const pathHash = primaryPathHash || secondaryPathHash;
|
||||
|
||||
return {
|
||||
isChannel,
|
||||
|
@ -127,6 +128,7 @@ export function parseURI(url: string, requireProto: boolean = false): LbryUrlObj
|
|||
...(primaryBidPosition ? { primaryBidPosition: parseInt(primaryBidPosition, 10) } : {}),
|
||||
...(secondaryBidPosition ? { secondaryBidPosition: parseInt(secondaryBidPosition, 10) } : {}),
|
||||
...(startTime ? { startTime: parseInt(startTime, 10) } : {}),
|
||||
...(pathHash ? { pathHash } : {}),
|
||||
|
||||
// The values below should not be used for new uses of parseURI
|
||||
// They will not work properly with canonical_urls
|
||||
|
@ -141,6 +143,7 @@ function parseURIModifier(modSeperator: ?string, modValue: ?string) {
|
|||
let claimId;
|
||||
let claimSequence;
|
||||
let bidPosition;
|
||||
let pathHash;
|
||||
|
||||
if (modSeperator) {
|
||||
if (!modValue) {
|
||||
|
@ -157,8 +160,18 @@ function parseURIModifier(modSeperator: ?string, modValue: ?string) {
|
|||
}
|
||||
|
||||
if (claimId && (claimId.length > claimIdMaxLength || !claimId.match(/^[0-9a-f]+$/))) {
|
||||
const hashIndex = claimId.indexOf('#');
|
||||
|
||||
if (hashIndex >= 0) {
|
||||
pathHash = claimId.substring(hashIndex);
|
||||
claimId = claimId.substring(0, hashIndex);
|
||||
// As a pre-caution to catch future odd urls coming in,
|
||||
// validate the new claimId length and characters again after stripping off the pathHash
|
||||
[claimId] = parseURIModifier(modSeperator, claimId);
|
||||
} else {
|
||||
throw new Error(__(`Invalid claim ID %claimId%.`, { claimId }));
|
||||
}
|
||||
}
|
||||
|
||||
if (claimSequence && !claimSequence.match(/^-?[1-9][0-9]*$/)) {
|
||||
throw new Error(__('Claim sequence must be a number.'));
|
||||
|
@ -168,7 +181,7 @@ function parseURIModifier(modSeperator: ?string, modValue: ?string) {
|
|||
throw new Error(__('Bid position must be a number.'));
|
||||
}
|
||||
|
||||
return [claimId, claimSequence, bidPosition];
|
||||
return [claimId, claimSequence, bidPosition, pathHash];
|
||||
}
|
||||
|
||||
const errorHistory = [];
|
||||
|
|
|
@ -205,7 +205,7 @@ async function buildClaimOgMetadata(uri, claim, overrideOptions = {}, referrerQu
|
|||
const title = overrideOptions.title || claimTitle;
|
||||
const description = overrideOptions.description || claimDescription;
|
||||
const cleanDescription = removeMd(description);
|
||||
const claimPath = `${URL}/${claim.canonical_url.replace('lbry://', '').replace('#', ':')}`;
|
||||
const claimPath = `${URL}/${claim.canonical_url.replace('lbry://', '').replace(/#/g, ':')}`;
|
||||
|
||||
let head = '';
|
||||
|
||||
|
|
|
@ -108,17 +108,18 @@ function parseURI(url, requireProto = false) {
|
|||
}
|
||||
|
||||
// Validate and process modifier
|
||||
const [primaryClaimId, primaryClaimSequence, primaryBidPosition] = parseURIModifier(
|
||||
const [primaryClaimId, primaryClaimSequence, primaryBidPosition, primaryPathHash] = parseURIModifier(
|
||||
primaryModSeparator,
|
||||
primaryModValue
|
||||
);
|
||||
const [secondaryClaimId, secondaryClaimSequence, secondaryBidPosition] = parseURIModifier(
|
||||
const [secondaryClaimId, secondaryClaimSequence, secondaryBidPosition, secondaryPathHash] = parseURIModifier(
|
||||
secondaryModSeparator,
|
||||
secondaryModValue
|
||||
);
|
||||
const streamName = includesChannel ? possibleStreamName : streamNameOrChannelName;
|
||||
const streamClaimId = includesChannel ? secondaryClaimId : primaryClaimId;
|
||||
const channelClaimId = includesChannel && primaryClaimId;
|
||||
const pathHash = primaryPathHash || secondaryPathHash;
|
||||
|
||||
return {
|
||||
isChannel,
|
||||
|
@ -132,6 +133,7 @@ function parseURI(url, requireProto = false) {
|
|||
...(primaryBidPosition ? { primaryBidPosition: parseInt(primaryBidPosition, 10) } : {}),
|
||||
...(secondaryBidPosition ? { secondaryBidPosition: parseInt(secondaryBidPosition, 10) } : {}),
|
||||
...(startTime ? { startTime: parseInt(startTime, 10) } : {}),
|
||||
...(pathHash ? { pathHash } : {}),
|
||||
|
||||
// The values below should not be used for new uses of parseURI
|
||||
// They will not work properly with canonical_urls
|
||||
|
@ -146,6 +148,7 @@ function parseURIModifier(modSeperator, modValue) {
|
|||
let claimId;
|
||||
let claimSequence;
|
||||
let bidPosition;
|
||||
let pathHash;
|
||||
|
||||
if (modSeperator) {
|
||||
if (!modValue) {
|
||||
|
@ -162,7 +165,17 @@ function parseURIModifier(modSeperator, modValue) {
|
|||
}
|
||||
|
||||
if (claimId && (claimId.length > claimIdMaxLength || !claimId.match(/^[0-9a-f]+$/))) {
|
||||
throw new Error(__(`Invalid claim ID ${claimId}.`, { claimId }));
|
||||
const hashIndex = claimId.indexOf('#');
|
||||
|
||||
if (hashIndex >= 0) {
|
||||
pathHash = claimId.substring(hashIndex);
|
||||
claimId = claimId.substring(0, hashIndex);
|
||||
// As a pre-caution to catch future odd urls coming in,
|
||||
// validate the new claimId length and characters again after stripping off the pathHash
|
||||
[claimId] = parseURIModifier(modSeperator, claimId);
|
||||
} else {
|
||||
throw new Error(__(`Invalid claim ID %claimId%.`, { claimId }));
|
||||
}
|
||||
}
|
||||
|
||||
if (claimSequence && !claimSequence.match(/^-?[1-9][0-9]*$/)) {
|
||||
|
@ -173,7 +186,7 @@ function parseURIModifier(modSeperator, modValue) {
|
|||
throw new Error(__('Bid position must be a number.'));
|
||||
}
|
||||
|
||||
return [claimId, claimSequence, bidPosition];
|
||||
return [claimId, claimSequence, bidPosition, pathHash];
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
Loading…
Reference in a new issue