use same code for handling open links on lbry.tv and desktop
This commit is contained in:
parent
8839bb08db
commit
bf512e8338
21 changed files with 156 additions and 140 deletions
|
@ -2,7 +2,7 @@ module.exports = api => {
|
||||||
api.cache(false);
|
api.cache(false);
|
||||||
|
|
||||||
return {
|
return {
|
||||||
presets: ['@babel/env', '@babel/react', '@babel/flow'],
|
presets: [['@babel/env', { loose: true, modules: false }], '@babel/react', '@babel/flow'],
|
||||||
plugins: [
|
plugins: [
|
||||||
'import-glob',
|
'import-glob',
|
||||||
'@babel/plugin-transform-runtime',
|
'@babel/plugin-transform-runtime',
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
const config = {
|
const config = {
|
||||||
WEBPACK_WEB_PORT: 9090,
|
WEBPACK_WEB_PORT: 9090,
|
||||||
WEBPACK_ELECTRON_PORT: 9091,
|
WEBPACK_ELECTRON_PORT: 9091,
|
||||||
WEB_SERVER_PORT: 80,
|
WEB_SERVER_PORT: 1337,
|
||||||
DOMAIN: 'lbry.tv',
|
DOMAIN: 'lbry.tv',
|
||||||
URL: 'https://lbry.tv',
|
URL: 'https://lbry.tv',
|
||||||
SITE_TITLE: 'lbry.tv',
|
SITE_TITLE: 'lbry.tv',
|
||||||
|
|
|
@ -1,5 +1,7 @@
|
||||||
const config = require('../../config');
|
const config = require('../../config');
|
||||||
const PAGES = require('../../ui/constants/pages');
|
const PAGES = require('../../ui/constants/pages');
|
||||||
|
const { formatCustomUrl } = require('../../ui/util/url');
|
||||||
|
const { parseURI } = require('lbry-redux');
|
||||||
|
|
||||||
async function redirectMiddleware(ctx, next) {
|
async function redirectMiddleware(ctx, next) {
|
||||||
const requestHost = ctx.host;
|
const requestHost = ctx.host;
|
||||||
|
@ -16,22 +18,14 @@ async function redirectMiddleware(ctx, next) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (requestHost === 'open.lbry.com') {
|
if (requestHost === 'open.lbry.com' || requestHost === 'open.lbry.io') {
|
||||||
let redirectUrl = config.URL;
|
|
||||||
const openQuery = '?src=open';
|
const openQuery = '?src=open';
|
||||||
const matches = /(\/\?)([a-z]*)(.*)/.exec(url);
|
let redirectUrl = config.URL + formatCustomUrl(url, openQuery);
|
||||||
|
|
||||||
if (matches && matches.length) {
|
if (redirectUrl.includes('?')) {
|
||||||
[, , page, queryString] = matches;
|
redirectUrl = redirectUrl.replace('?', `${openQuery}&`);
|
||||||
|
|
||||||
// This is a lbry app page. Make sure to add the leading `/$/`
|
|
||||||
if (page && Object.values(PAGES).includes(page)) {
|
|
||||||
redirectUrl += '/$/' + page;
|
|
||||||
}
|
|
||||||
|
|
||||||
redirectUrl += openQuery + queryString;
|
|
||||||
} else {
|
} else {
|
||||||
redirectUrl += path + openQuery;
|
redirectUrl += openQuery;
|
||||||
}
|
}
|
||||||
|
|
||||||
ctx.redirect(redirectUrl);
|
ctx.redirect(redirectUrl);
|
||||||
|
|
|
@ -4,7 +4,7 @@ import React, { forwardRef, useRef } from 'react';
|
||||||
import Icon from 'component/common/icon';
|
import Icon from 'component/common/icon';
|
||||||
import classnames from 'classnames';
|
import classnames from 'classnames';
|
||||||
import { NavLink } from 'react-router-dom';
|
import { NavLink } from 'react-router-dom';
|
||||||
import { formatLbryUriForWeb } from 'util/uri';
|
import { formatLbryUrlForWeb } from 'util/url';
|
||||||
import { OutboundLink } from 'react-ga';
|
import { OutboundLink } from 'react-ga';
|
||||||
import * as PAGES from 'constants/pages';
|
import * as PAGES from 'constants/pages';
|
||||||
import useCombinedRefs from 'effects/use-combined-refs';
|
import useCombinedRefs from 'effects/use-combined-refs';
|
||||||
|
@ -108,7 +108,7 @@ const Button = forwardRef<any, {}>((props: Props, ref: any) => {
|
||||||
let path = navigate;
|
let path = navigate;
|
||||||
if (path) {
|
if (path) {
|
||||||
if (path.startsWith('lbry://')) {
|
if (path.startsWith('lbry://')) {
|
||||||
path = formatLbryUriForWeb(path);
|
path = formatLbryUrlForWeb(path);
|
||||||
} else if (!path.startsWith('/')) {
|
} else if (!path.startsWith('/')) {
|
||||||
// Force a leading slash so new paths aren't appended on to the current path
|
// Force a leading slash so new paths aren't appended on to the current path
|
||||||
path = `/${path}`;
|
path = `/${path}`;
|
||||||
|
|
|
@ -5,7 +5,7 @@ import classnames from 'classnames';
|
||||||
import { parseURI, convertToShareLink } from 'lbry-redux';
|
import { parseURI, convertToShareLink } from 'lbry-redux';
|
||||||
import { withRouter } from 'react-router-dom';
|
import { withRouter } from 'react-router-dom';
|
||||||
import { openCopyLinkMenu } from 'util/context-menu';
|
import { openCopyLinkMenu } from 'util/context-menu';
|
||||||
import { formatLbryUriForWeb } from 'util/uri';
|
import { formatLbryUrlForWeb } from 'util/url';
|
||||||
import { isEmpty } from 'util/object';
|
import { isEmpty } from 'util/object';
|
||||||
import CardMedia from 'component/cardMedia';
|
import CardMedia from 'component/cardMedia';
|
||||||
import UriIndicator from 'component/uriIndicator';
|
import UriIndicator from 'component/uriIndicator';
|
||||||
|
@ -149,7 +149,7 @@ const ClaimPreview = forwardRef<any, {}>((props: Props, ref: any) => {
|
||||||
if (onClick) {
|
if (onClick) {
|
||||||
onClick(e);
|
onClick(e);
|
||||||
} else if ((isChannel || title) && !pending) {
|
} else if ((isChannel || title) && !pending) {
|
||||||
history.push(formatLbryUriForWeb(claim && claim.canonical_url ? claim.canonical_url : uri));
|
history.push(formatLbryUrlForWeb(claim && claim.canonical_url ? claim.canonical_url : uri));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -5,7 +5,7 @@ import * as React from 'react';
|
||||||
import { isURIValid } from 'lbry-redux';
|
import { isURIValid } from 'lbry-redux';
|
||||||
import Button from 'component/button';
|
import Button from 'component/button';
|
||||||
import ClaimLink from 'component/claimLink';
|
import ClaimLink from 'component/claimLink';
|
||||||
import { isLBRYDomain } from 'util/uri';
|
import { isLBRYDomain } from 'util/url';
|
||||||
|
|
||||||
type Props = {
|
type Props = {
|
||||||
href: string,
|
href: string,
|
||||||
|
|
|
@ -7,7 +7,7 @@ import ImageViewer from 'component/viewers/imageViewer';
|
||||||
import AppViewer from 'component/viewers/appViewer';
|
import AppViewer from 'component/viewers/appViewer';
|
||||||
import Button from 'component/button';
|
import Button from 'component/button';
|
||||||
import { withRouter } from 'react-router-dom';
|
import { withRouter } from 'react-router-dom';
|
||||||
import { formatLbryUriForWeb } from 'util/uri';
|
import { formatLbryUrlForWeb } from 'util/url';
|
||||||
// @if TARGET='web'
|
// @if TARGET='web'
|
||||||
import { generateStreamUrl } from 'util/lbrytv';
|
import { generateStreamUrl } from 'util/lbrytv';
|
||||||
// @endif
|
// @endif
|
||||||
|
@ -73,7 +73,7 @@ class FileRender extends React.PureComponent<Props> {
|
||||||
onEndedCb() {
|
onEndedCb() {
|
||||||
const { autoplay, nextUnplayed, history } = this.props;
|
const { autoplay, nextUnplayed, history } = this.props;
|
||||||
if (autoplay && nextUnplayed) {
|
if (autoplay && nextUnplayed) {
|
||||||
history.push(formatLbryUriForWeb(nextUnplayed));
|
history.push(formatLbryUrlForWeb(nextUnplayed));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -5,7 +5,7 @@ import classnames from 'classnames';
|
||||||
import Button from 'component/button';
|
import Button from 'component/button';
|
||||||
import { FormField } from 'component/common/form';
|
import { FormField } from 'component/common/form';
|
||||||
import { withRouter } from 'react-router-dom';
|
import { withRouter } from 'react-router-dom';
|
||||||
import { formatLbryUriForWeb } from 'util/uri';
|
import { formatLbryUrlForWeb } from 'util/url';
|
||||||
|
|
||||||
type Props = {
|
type Props = {
|
||||||
lastViewed: number,
|
lastViewed: number,
|
||||||
|
@ -39,7 +39,7 @@ class NavigationHistoryItem extends React.PureComponent<Props> {
|
||||||
({ title } = claim.value);
|
({ title } = claim.value);
|
||||||
}
|
}
|
||||||
|
|
||||||
const navigatePath = formatLbryUriForWeb(uri);
|
const navigatePath = formatLbryUrlForWeb(uri);
|
||||||
const onClick =
|
const onClick =
|
||||||
onSelect ||
|
onSelect ||
|
||||||
function() {
|
function() {
|
||||||
|
|
|
@ -4,7 +4,7 @@ import UriIndicator from 'component/uriIndicator';
|
||||||
import TruncatedText from 'component/common/truncated-text';
|
import TruncatedText from 'component/common/truncated-text';
|
||||||
import MarkdownPreview from 'component/common/markdown-preview';
|
import MarkdownPreview from 'component/common/markdown-preview';
|
||||||
import { withRouter } from 'react-router-dom';
|
import { withRouter } from 'react-router-dom';
|
||||||
import { formatLbryUriForWeb } from 'util/uri';
|
import { formatLbryUrlForWeb } from 'util/url';
|
||||||
|
|
||||||
type Props = {
|
type Props = {
|
||||||
uri: string,
|
uri: string,
|
||||||
|
@ -17,7 +17,7 @@ type Props = {
|
||||||
class PreviewLink extends React.PureComponent<Props> {
|
class PreviewLink extends React.PureComponent<Props> {
|
||||||
handleClick = () => {
|
handleClick = () => {
|
||||||
const { uri, history } = this.props;
|
const { uri, history } = this.props;
|
||||||
history.push(formatLbryUriForWeb(uri));
|
history.push(formatLbryUrlForWeb(uri));
|
||||||
};
|
};
|
||||||
|
|
||||||
render() {
|
render() {
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
// @flow
|
// @flow
|
||||||
import * as PAGES from 'constants/pages';
|
import * as PAGES from 'constants/pages';
|
||||||
import React, { useEffect, Suspense } from 'react';
|
import React, { useEffect } from 'react';
|
||||||
import { Route, Redirect, Switch, withRouter } from 'react-router-dom';
|
import { Route, Redirect, Switch, withRouter } from 'react-router-dom';
|
||||||
import SettingsPage from 'page/settings';
|
import SettingsPage from 'page/settings';
|
||||||
import HelpPage from 'page/help';
|
import HelpPage from 'page/help';
|
||||||
|
@ -69,37 +69,35 @@ function AppRouter(props: Props) {
|
||||||
}, [currentScroll, pathname]);
|
}, [currentScroll, pathname]);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Suspense fallback={<span>LODIFJDSLKJFSLDKJFLDJ</span>}>
|
<Switch>
|
||||||
<Switch>
|
<Route path="/" exact component={DiscoverPage} />
|
||||||
<Route path="/" exact component={DiscoverPage} />
|
<Route path={`/$/${PAGES.DISCOVER}`} exact component={DiscoverPage} />
|
||||||
<Route path={`/$/${PAGES.DISCOVER}`} exact component={DiscoverPage} />
|
<Route path={`/$/${PAGES.AUTH}`} exact component={SignInPage} />
|
||||||
<Route path={`/$/${PAGES.AUTH}`} exact component={SignInPage} />
|
<Route path={`/$/${PAGES.TAGS}`} exact component={TagsPage} />
|
||||||
<Route path={`/$/${PAGES.TAGS}`} exact component={TagsPage} />
|
<Route path={`/$/${PAGES.HELP}`} exact component={HelpPage} />
|
||||||
<Route path={`/$/${PAGES.HELP}`} exact component={HelpPage} />
|
<Route path={`/$/${PAGES.AUTH_VERIFY}`} exact component={SignInVerifyPage} />
|
||||||
<Route path={`/$/${PAGES.AUTH_VERIFY}`} exact component={SignInVerifyPage} />
|
<Route path={`/$/${PAGES.SEARCH}`} exact component={SearchPage} />
|
||||||
<Route path={`/$/${PAGES.SEARCH}`} exact component={SearchPage} />
|
<Route path={`/$/${PAGES.SETTINGS}`} exact component={SettingsPage} />
|
||||||
<Route path={`/$/${PAGES.SETTINGS}`} exact component={SettingsPage} />
|
|
||||||
|
|
||||||
<PrivateRoute {...props} path={`/$/${PAGES.INVITE}`} component={InvitePage} />
|
<PrivateRoute {...props} path={`/$/${PAGES.INVITE}`} component={InvitePage} />
|
||||||
<PrivateRoute {...props} path={`/$/${PAGES.DOWNLOADED}`} component={FileListDownloaded} />
|
<PrivateRoute {...props} path={`/$/${PAGES.DOWNLOADED}`} component={FileListDownloaded} />
|
||||||
<PrivateRoute {...props} path={`/$/${PAGES.PUBLISHED}`} component={FileListPublished} />
|
<PrivateRoute {...props} path={`/$/${PAGES.PUBLISHED}`} component={FileListPublished} />
|
||||||
<PrivateRoute {...props} path={`/$/${PAGES.PUBLISH}`} component={PublishPage} />
|
<PrivateRoute {...props} path={`/$/${PAGES.PUBLISH}`} component={PublishPage} />
|
||||||
<PrivateRoute {...props} path={`/$/${PAGES.REPORT}`} component={ReportPage} />
|
<PrivateRoute {...props} path={`/$/${PAGES.REPORT}`} component={ReportPage} />
|
||||||
<PrivateRoute {...props} path={`/$/${PAGES.REWARDS}`} component={RewardsPage} />
|
<PrivateRoute {...props} path={`/$/${PAGES.REWARDS}`} component={RewardsPage} />
|
||||||
<PrivateRoute {...props} path={`/$/${PAGES.TRANSACTIONS}`} component={TransactionHistoryPage} />
|
<PrivateRoute {...props} path={`/$/${PAGES.TRANSACTIONS}`} component={TransactionHistoryPage} />
|
||||||
<PrivateRoute {...props} path={`/$/${PAGES.LIBRARY}`} component={LibraryPage} />
|
<PrivateRoute {...props} path={`/$/${PAGES.LIBRARY}`} component={LibraryPage} />
|
||||||
<PrivateRoute {...props} path={`/$/${PAGES.ACCOUNT}`} component={AccountPage} />
|
<PrivateRoute {...props} path={`/$/${PAGES.ACCOUNT}`} component={AccountPage} />
|
||||||
<PrivateRoute {...props} path={`/$/${PAGES.FOLLOWING}`} component={FollowingPage} />
|
<PrivateRoute {...props} path={`/$/${PAGES.FOLLOWING}`} component={FollowingPage} />
|
||||||
<PrivateRoute {...props} path={`/$/${PAGES.BLOCKED}`} component={ListBlockedPage} />
|
<PrivateRoute {...props} path={`/$/${PAGES.BLOCKED}`} component={ListBlockedPage} />
|
||||||
<PrivateRoute {...props} path={`/$/${PAGES.WALLET}`} exact component={WalletPage} />
|
<PrivateRoute {...props} path={`/$/${PAGES.WALLET}`} exact component={WalletPage} />
|
||||||
<PrivateRoute {...props} path={`/$/${PAGES.CHANNELS}`} component={ChannelsPage} />
|
<PrivateRoute {...props} path={`/$/${PAGES.CHANNELS}`} component={ChannelsPage} />
|
||||||
|
|
||||||
{/* Below need to go at the end to make sure we don't match any of our pages first */}
|
{/* Below need to go at the end to make sure we don't match any of our pages first */}
|
||||||
<Route path="/:claimName" exact component={ShowPage} />
|
<Route path="/:claimName" exact component={ShowPage} />
|
||||||
<Route path="/:claimName/:streamName" exact component={ShowPage} />
|
<Route path="/:claimName/:streamName" exact component={ShowPage} />
|
||||||
<Route path="/*" component={FourOhFourPage} />
|
<Route path="/*" component={FourOhFourPage} />
|
||||||
</Switch>
|
</Switch>
|
||||||
</Suspense>
|
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -11,7 +11,7 @@ import {
|
||||||
import analytics from 'analytics';
|
import analytics from 'analytics';
|
||||||
import Wunderbar from './view';
|
import Wunderbar from './view';
|
||||||
import { withRouter } from 'react-router-dom';
|
import { withRouter } from 'react-router-dom';
|
||||||
import { formatLbryUriForWeb } from 'util/uri';
|
import { formatLbryUrlForWeb } from 'util/url';
|
||||||
|
|
||||||
const select = state => ({
|
const select = state => ({
|
||||||
suggestions: selectSearchSuggestions(state),
|
suggestions: selectSearchSuggestions(state),
|
||||||
|
@ -26,7 +26,7 @@ const perform = (dispatch, ownProps) => ({
|
||||||
analytics.apiLogSearch();
|
analytics.apiLogSearch();
|
||||||
},
|
},
|
||||||
onSubmit: uri => {
|
onSubmit: uri => {
|
||||||
const path = formatLbryUriForWeb(uri);
|
const path = formatLbryUrlForWeb(uri);
|
||||||
ownProps.history.push(path);
|
ownProps.history.push(path);
|
||||||
dispatch(doUpdateSearchQuery(''));
|
dispatch(doUpdateSearchQuery(''));
|
||||||
},
|
},
|
||||||
|
|
45
ui/index.jsx
45
ui/index.jsx
|
@ -13,7 +13,7 @@ import * as MODALS from 'constants/modal_types';
|
||||||
import React, { Fragment, useState, useEffect } from 'react';
|
import React, { Fragment, useState, useEffect } from 'react';
|
||||||
import ReactDOM from 'react-dom';
|
import ReactDOM from 'react-dom';
|
||||||
import { Provider } from 'react-redux';
|
import { Provider } from 'react-redux';
|
||||||
import { doConditionalAuthNavigate, doDaemonReady, doAutoUpdate, doOpenModal, doHideModal } from 'redux/actions/app';
|
import { doDaemonReady, doAutoUpdate, doOpenModal, doHideModal } from 'redux/actions/app';
|
||||||
import { Lbry, doToast, isURIValid, setSearchApi, apiCall } from 'lbry-redux';
|
import { Lbry, doToast, isURIValid, setSearchApi, apiCall } from 'lbry-redux';
|
||||||
import { doSetLanguage, doUpdateIsNightAsync } from 'redux/actions/settings';
|
import { doSetLanguage, doUpdateIsNightAsync } from 'redux/actions/settings';
|
||||||
import {
|
import {
|
||||||
|
@ -28,7 +28,7 @@ import pjson from 'package.json';
|
||||||
import app from './app';
|
import app from './app';
|
||||||
import doLogWarningConsoleMessage from './logWarningConsoleMessage';
|
import doLogWarningConsoleMessage from './logWarningConsoleMessage';
|
||||||
import { ConnectedRouter, push } from 'connected-react-router';
|
import { ConnectedRouter, push } from 'connected-react-router';
|
||||||
import { formatLbryUriForWeb } from 'util/uri';
|
import { formatLbryUrlForWeb, formatCustomUrl } from 'util/url';
|
||||||
import { PersistGate } from 'redux-persist/integration/react';
|
import { PersistGate } from 'redux-persist/integration/react';
|
||||||
import analytics from 'analytics';
|
import analytics from 'analytics';
|
||||||
import { getAuthToken, setAuthToken } from 'util/saved-passwords';
|
import { getAuthToken, setAuthToken } from 'util/saved-passwords';
|
||||||
|
@ -70,7 +70,6 @@ Lbry.setOverride(
|
||||||
const startTime = Date.now();
|
const startTime = Date.now();
|
||||||
analytics.startupEvent();
|
analytics.startupEvent();
|
||||||
|
|
||||||
const APPPAGEURL = 'lbry://?';
|
|
||||||
// @if TARGET='app'
|
// @if TARGET='app'
|
||||||
const { autoUpdater } = remote.require('electron-updater');
|
const { autoUpdater } = remote.require('electron-updater');
|
||||||
autoUpdater.logger = remote.require('electron-log');
|
autoUpdater.logger = remote.require('electron-log');
|
||||||
|
@ -157,25 +156,29 @@ rewards.setCallback('claimRewardSuccess', () => {
|
||||||
});
|
});
|
||||||
|
|
||||||
// @if TARGET='app'
|
// @if TARGET='app'
|
||||||
ipcRenderer.on('open-uri-requested', (event, uri, newSession) => {
|
ipcRenderer.on('open-uri-requested', (event, url, newSession) => {
|
||||||
if (uri && uri.startsWith('lbry://')) {
|
function handleError() {
|
||||||
if (uri.startsWith('lbry://?verify')) {
|
app.store.dispatch(
|
||||||
app.store.dispatch(doConditionalAuthNavigate(newSession));
|
doToast({
|
||||||
} else if (uri.startsWith(APPPAGEURL)) {
|
message: __('Invalid LBRY URL requested'),
|
||||||
const navpage = uri.replace(APPPAGEURL, '').toLowerCase();
|
})
|
||||||
app.store.dispatch(push(`/$/${navpage}`));
|
);
|
||||||
} else if (isURIValid(uri)) {
|
|
||||||
const formattedUri = formatLbryUriForWeb(uri);
|
|
||||||
app.store.dispatch(push(formattedUri));
|
|
||||||
analytics.openUrlEvent(formattedUri);
|
|
||||||
} else {
|
|
||||||
app.store.dispatch(
|
|
||||||
doToast({
|
|
||||||
message: __('Invalid LBRY URL requested'),
|
|
||||||
})
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const path = url.slice('lbry://'.length);
|
||||||
|
if (path.startsWith('?')) {
|
||||||
|
const redirectUrl = formatCustomUrl(path);
|
||||||
|
return app.store.dispatch(push(redirectUrl));
|
||||||
|
}
|
||||||
|
|
||||||
|
if (isURIValid(url)) {
|
||||||
|
const formattedUrl = formatLbryUrlForWeb(url);
|
||||||
|
analytics.openUrlEvent(formattedUrl);
|
||||||
|
return app.store.dispatch(push(formattedUrl));
|
||||||
|
}
|
||||||
|
|
||||||
|
// If nothing redirected before here the url must be messed up
|
||||||
|
handleError();
|
||||||
});
|
});
|
||||||
|
|
||||||
ipcRenderer.on('language-set', (event, language) => {
|
ipcRenderer.on('language-set', (event, language) => {
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
// @flow
|
// @flow
|
||||||
import React, { useRef } from 'react';
|
import React, { useRef } from 'react';
|
||||||
import { Modal } from 'modal/modal';
|
import { Modal } from 'modal/modal';
|
||||||
import { formatPathForWeb } from 'util/uri';
|
import { formatFileSystemPath } from 'util/url';
|
||||||
|
|
||||||
type Props = {
|
type Props = {
|
||||||
upload: WebFile => void,
|
upload: WebFile => void,
|
||||||
|
@ -15,7 +15,7 @@ function ModalAutoGenerateThumbnail(props: Props) {
|
||||||
const playerRef = useRef();
|
const playerRef = useRef();
|
||||||
let videoSrc;
|
let videoSrc;
|
||||||
if (typeof filePath === 'string') {
|
if (typeof filePath === 'string') {
|
||||||
videoSrc = formatPathForWeb(filePath);
|
videoSrc = formatFileSystemPath(filePath);
|
||||||
} else {
|
} else {
|
||||||
videoSrc = URL.createObjectURL(filePath);
|
videoSrc = URL.createObjectURL(filePath);
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
// @flow
|
// @flow
|
||||||
import React from 'react';
|
import React from 'react';
|
||||||
import { Modal } from 'modal/modal';
|
import { Modal } from 'modal/modal';
|
||||||
import { formatPathForWeb } from 'util/uri';
|
import { formatFileSystemPath } from 'util/url';
|
||||||
// @if TARGET='app'
|
// @if TARGET='app'
|
||||||
import { shell } from 'electron';
|
import { shell } from 'electron';
|
||||||
// @endif
|
// @endif
|
||||||
|
@ -37,7 +37,7 @@ function ModalOpenExternalResource(props: Props) {
|
||||||
if (uri) {
|
if (uri) {
|
||||||
window.open(uri);
|
window.open(uri);
|
||||||
} else if (path) {
|
} else if (path) {
|
||||||
window.open(formatPathForWeb(path));
|
window.open(formatFileSystemPath(path));
|
||||||
}
|
}
|
||||||
// @endif
|
// @endif
|
||||||
|
|
||||||
|
|
|
@ -8,7 +8,7 @@ import ShareButton from 'component/shareButton';
|
||||||
import { Tabs, TabList, Tab, TabPanels, TabPanel } from 'component/common/tabs';
|
import { Tabs, TabList, Tab, TabPanels, TabPanel } from 'component/common/tabs';
|
||||||
import { withRouter } from 'react-router';
|
import { withRouter } from 'react-router';
|
||||||
import Button from 'component/button';
|
import Button from 'component/button';
|
||||||
import { formatLbryUriForWeb } from 'util/uri';
|
import { formatLbryUrlForWeb } from 'util/url';
|
||||||
import ChannelContent from 'component/channelContent';
|
import ChannelContent from 'component/channelContent';
|
||||||
import ChannelAbout from 'component/channelAbout';
|
import ChannelAbout from 'component/channelAbout';
|
||||||
import ChannelDiscussion from 'component/channelDiscussion';
|
import ChannelDiscussion from 'component/channelDiscussion';
|
||||||
|
@ -93,7 +93,7 @@ function ChannelPage(props: Props) {
|
||||||
const tabIndex = currentView === ABOUT_PAGE || editing ? 1 : currentView === DISCUSSION_PAGE ? 2 : 0;
|
const tabIndex = currentView === ABOUT_PAGE || editing ? 1 : currentView === DISCUSSION_PAGE ? 2 : 0;
|
||||||
|
|
||||||
function onTabChange(newTabIndex) {
|
function onTabChange(newTabIndex) {
|
||||||
let url = formatLbryUriForWeb(uri);
|
let url = formatLbryUrlForWeb(uri);
|
||||||
let search = '?';
|
let search = '?';
|
||||||
|
|
||||||
if (newTabIndex === 0) {
|
if (newTabIndex === 0) {
|
||||||
|
|
|
@ -6,7 +6,6 @@ import { ipcRenderer, remote } from 'electron';
|
||||||
import path from 'path';
|
import path from 'path';
|
||||||
import * as ACTIONS from 'constants/action_types';
|
import * as ACTIONS from 'constants/action_types';
|
||||||
import * as MODALS from 'constants/modal_types';
|
import * as MODALS from 'constants/modal_types';
|
||||||
import * as PAGES from 'constants/pages';
|
|
||||||
import {
|
import {
|
||||||
Lbry,
|
Lbry,
|
||||||
doBalanceSubscribe,
|
doBalanceSubscribe,
|
||||||
|
@ -36,7 +35,6 @@ import {
|
||||||
} from 'redux/selectors/app';
|
} from 'redux/selectors/app';
|
||||||
import { doAuthenticate, doGetSync } from 'lbryinc';
|
import { doAuthenticate, doGetSync } from 'lbryinc';
|
||||||
import { lbrySettings as config, version as appVersion } from 'package.json';
|
import { lbrySettings as config, version as appVersion } from 'package.json';
|
||||||
import { push } from 'connected-react-router';
|
|
||||||
import analytics from 'analytics';
|
import analytics from 'analytics';
|
||||||
import { doSignOutCleanup, deleteSavedPassword, getSavedPassword } from 'util/saved-passwords';
|
import { doSignOutCleanup, deleteSavedPassword, getSavedPassword } from 'util/saved-passwords';
|
||||||
|
|
||||||
|
@ -404,17 +402,6 @@ export function doClickCommentButton() {
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
export function doConditionalAuthNavigate(newSession) {
|
|
||||||
return (dispatch, getState) => {
|
|
||||||
const state = getState();
|
|
||||||
const modal = selectModal(state);
|
|
||||||
|
|
||||||
if (newSession || (modal && modal.id !== MODALS.EMAIL_COLLECTION)) {
|
|
||||||
dispatch(push(`/$/${PAGES.AUTH}`));
|
|
||||||
}
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
export function doToggleSearchExpanded() {
|
export function doToggleSearchExpanded() {
|
||||||
return {
|
return {
|
||||||
type: ACTIONS.TOGGLE_SEARCH_EXPANDED,
|
type: ACTIONS.TOGGLE_SEARCH_EXPANDED,
|
||||||
|
|
|
@ -25,7 +25,7 @@ import {
|
||||||
} from 'lbry-redux';
|
} from 'lbry-redux';
|
||||||
import { makeSelectCostInfoForUri } from 'lbryinc';
|
import { makeSelectCostInfoForUri } from 'lbryinc';
|
||||||
import { makeSelectClientSetting, selectosNotificationsEnabled, selectDaemonSettings } from 'redux/selectors/settings';
|
import { makeSelectClientSetting, selectosNotificationsEnabled, selectDaemonSettings } from 'redux/selectors/settings';
|
||||||
import { formatLbryUriForWeb } from 'util/uri';
|
import { formatLbryUrlForWeb } from 'util/url';
|
||||||
|
|
||||||
const DOWNLOAD_POLL_INTERVAL = 250;
|
const DOWNLOAD_POLL_INTERVAL = 250;
|
||||||
|
|
||||||
|
@ -85,7 +85,7 @@ export function doUpdateLoadStatus(uri: string, outpoint: string) {
|
||||||
silent: false,
|
silent: false,
|
||||||
});
|
});
|
||||||
notif.onclick = () => {
|
notif.onclick = () => {
|
||||||
dispatch(push(formatLbryUriForWeb(uri)));
|
dispatch(push(formatLbryUrlForWeb(uri)));
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -6,7 +6,7 @@ import { batchActions, doError, selectMyClaims, doPublish, doCheckPendingPublish
|
||||||
import { selectosNotificationsEnabled } from 'redux/selectors/settings';
|
import { selectosNotificationsEnabled } from 'redux/selectors/settings';
|
||||||
import { push } from 'connected-react-router';
|
import { push } from 'connected-react-router';
|
||||||
import analytics from 'analytics';
|
import analytics from 'analytics';
|
||||||
import { formatLbryUriForWeb } from 'util/uri';
|
import { formatLbryUrlForWeb } from 'util/url';
|
||||||
import { doOpenModal } from './app';
|
import { doOpenModal } from './app';
|
||||||
|
|
||||||
export const doPublishDesktop = (filePath: string) => (dispatch: Dispatch, getState: () => {}) => {
|
export const doPublishDesktop = (filePath: string) => (dispatch: Dispatch, getState: () => {}) => {
|
||||||
|
@ -81,7 +81,7 @@ export const doCheckPendingPublishesApp = () => (dispatch: Dispatch, getState: G
|
||||||
silent: false,
|
silent: false,
|
||||||
});
|
});
|
||||||
notif.onclick = () => {
|
notif.onclick = () => {
|
||||||
dispatch(push(formatLbryUriForWeb(claim.permanent_url)));
|
dispatch(push(formatLbryUrlForWeb(claim.permanent_url)));
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
|
@ -6,6 +6,10 @@
|
||||||
color: var(--color-text-selection);
|
color: var(--color-text-selection);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
*:focus {
|
||||||
|
outline: none;
|
||||||
|
}
|
||||||
|
|
||||||
html {
|
html {
|
||||||
@include font-sans;
|
@include font-sans;
|
||||||
height: 100%;
|
height: 100%;
|
||||||
|
|
|
@ -1,38 +0,0 @@
|
||||||
// @flow
|
|
||||||
|
|
||||||
const LBRY_INC_DOMAINS = ['lbry.io', 'lbry.com', 'lbry.tv', 'lbry.tech', 'lbry.fund', 'spee.ch'];
|
|
||||||
|
|
||||||
export const formatLbryUriForWeb = (uri: string) => {
|
|
||||||
return uri.replace('lbry://', '/').replace(/#/g, ':');
|
|
||||||
};
|
|
||||||
|
|
||||||
export const formatPathForWeb = (path: string) => {
|
|
||||||
if (!path) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
let webUrl = path.replace(/\\/g, '/');
|
|
||||||
|
|
||||||
if (webUrl[0] !== '/') {
|
|
||||||
webUrl = `/${webUrl}`;
|
|
||||||
}
|
|
||||||
|
|
||||||
return encodeURI(`file://${webUrl}`).replace(/[?#]/g, encodeURIComponent);
|
|
||||||
};
|
|
||||||
|
|
||||||
export const isLBRYDomain = (uri: string) => {
|
|
||||||
if (!uri) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
const myURL = new URL(uri);
|
|
||||||
const hostname = myURL.hostname;
|
|
||||||
|
|
||||||
for (let domain of LBRY_INC_DOMAINS) {
|
|
||||||
if (hostname.endsWith(domain)) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return false;
|
|
||||||
};
|
|
68
ui/util/url.js
Normal file
68
ui/util/url.js
Normal file
|
@ -0,0 +1,68 @@
|
||||||
|
const LBRY_INC_DOMAINS = ['lbry.io', 'lbry.com', 'lbry.tv', 'lbry.tech', 'lbry.fund', 'spee.ch'];
|
||||||
|
|
||||||
|
exports.formatLbryUrlForWeb = uri => {
|
||||||
|
return uri.replace('lbry://', '/').replace(/#/g, ':');
|
||||||
|
};
|
||||||
|
|
||||||
|
exports.formatFileSystemPath = path => {
|
||||||
|
if (!path) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
let webUrl = path.replace(/\\/g, '/');
|
||||||
|
|
||||||
|
if (webUrl[0] !== '/') {
|
||||||
|
webUrl = `/${webUrl}`;
|
||||||
|
}
|
||||||
|
|
||||||
|
return encodeURI(`file://${webUrl}`).replace(/[?#]/g, encodeURIComponent);
|
||||||
|
};
|
||||||
|
|
||||||
|
exports.isLBRYDomain = uri => {
|
||||||
|
if (!uri) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const myURL = new URL(uri);
|
||||||
|
const hostname = myURL.hostname;
|
||||||
|
|
||||||
|
for (let domain of LBRY_INC_DOMAINS) {
|
||||||
|
if (hostname.endsWith(domain)) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
};
|
||||||
|
|
||||||
|
/*
|
||||||
|
Function that handles page redirects
|
||||||
|
ex: lbry://?rewards
|
||||||
|
ex: open.lbry.com/?rewards
|
||||||
|
*/
|
||||||
|
exports.formatCustomUrl = path => {
|
||||||
|
// Determine if we need to add a leading "/$/" for app pages
|
||||||
|
const APP_PAGE_REGEX = /(\?)([a-z]*)(.*)/;
|
||||||
|
const appPageMatches = APP_PAGE_REGEX.exec(path);
|
||||||
|
|
||||||
|
if (appPageMatches && appPageMatches.length) {
|
||||||
|
// Definitely an app page (or it's formatted like one)
|
||||||
|
const [, , page, queryString] = appPageMatches;
|
||||||
|
let actualUrl = '/$/' + page;
|
||||||
|
|
||||||
|
if (queryString) {
|
||||||
|
if (queryString.startsWith('?')) {
|
||||||
|
actualUrl += queryString;
|
||||||
|
} else if (queryString.startsWith('&')) {
|
||||||
|
// Replace the leading "&" with a "?" because we must have lost the "?" from the page name
|
||||||
|
// /?rewards&a=b => /$/rewards?a=b
|
||||||
|
actualUrl += `?${queryString.slice(1)}`;
|
||||||
|
}
|
||||||
|
|
||||||
|
return actualUrl;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Regular claim url
|
||||||
|
return path;
|
||||||
|
};
|
Loading…
Reference in a new issue