cut SIMPLE_SITE
This commit is contained in:
parent
9694242989
commit
3a77c7507b
54 changed files with 326 additions and 1135 deletions
|
@ -2190,5 +2190,8 @@
|
||||||
"%totalComments% comments": "%totalComments% comments",
|
"%totalComments% comments": "%totalComments% comments",
|
||||||
"(%lbc_balance% available)": "(%lbc_balance% available)",
|
"(%lbc_balance% available)": "(%lbc_balance% available)",
|
||||||
"Sending...": "Sending...",
|
"Sending...": "Sending...",
|
||||||
|
"Trending for #Art": "Trending for #Art",
|
||||||
|
"Trending for #Btc": "Trending for #Btc",
|
||||||
|
"Trending for #Music": "Trending for #Music",
|
||||||
"--end--": "--end--"
|
"--end--": "--end--"
|
||||||
}
|
}
|
||||||
|
|
|
@ -4,8 +4,6 @@ import React, { useEffect, useRef, useState, useLayoutEffect } from 'react';
|
||||||
import { lazyImport } from 'util/lazyImport';
|
import { lazyImport } from 'util/lazyImport';
|
||||||
import classnames from 'classnames';
|
import classnames from 'classnames';
|
||||||
import analytics from 'analytics';
|
import analytics from 'analytics';
|
||||||
import { buildURI, parseURI } from 'util/lbryURI';
|
|
||||||
import { SIMPLE_SITE } from 'config';
|
|
||||||
import Router from 'component/router/index';
|
import Router from 'component/router/index';
|
||||||
import ReactModal from 'react-modal';
|
import ReactModal from 'react-modal';
|
||||||
import { openContextMenu } from 'util/context-menu';
|
import { openContextMenu } from 'util/context-menu';
|
||||||
|
@ -15,45 +13,14 @@ import { withRouter } from 'react-router';
|
||||||
import usePrevious from 'effects/use-previous';
|
import usePrevious from 'effects/use-previous';
|
||||||
import REWARDS from 'rewards';
|
import REWARDS from 'rewards';
|
||||||
import usePersistedState from 'effects/use-persisted-state';
|
import usePersistedState from 'effects/use-persisted-state';
|
||||||
import Spinner from 'component/spinner';
|
|
||||||
import LANGUAGES from 'constants/languages';
|
import LANGUAGES from 'constants/languages';
|
||||||
// @if TARGET='app'
|
|
||||||
import useZoom from 'effects/use-zoom';
|
import useZoom from 'effects/use-zoom';
|
||||||
import useHistoryNav from 'effects/use-history-nav';
|
import useHistoryNav from 'effects/use-history-nav';
|
||||||
// @endif
|
|
||||||
// @if TARGET='web'
|
|
||||||
import {
|
|
||||||
useDegradedPerformance,
|
|
||||||
STATUS_OK,
|
|
||||||
STATUS_DEGRADED,
|
|
||||||
STATUS_FAILING,
|
|
||||||
STATUS_DOWN,
|
|
||||||
} from 'web/effects/use-degraded-performance';
|
|
||||||
// @endif
|
|
||||||
import LANGUAGE_MIGRATIONS from 'constants/language-migrations';
|
import LANGUAGE_MIGRATIONS from 'constants/language-migrations';
|
||||||
|
|
||||||
const FileDrop = lazyImport(() => import('component/fileDrop' /* webpackChunkName: "secondary" */));
|
const FileDrop = lazyImport(() => import('component/fileDrop' /* webpackChunkName: "secondary" */));
|
||||||
const ModalRouter = lazyImport(() => import('modal/modalRouter' /* webpackChunkName: "secondary" */));
|
const ModalRouter = lazyImport(() => import('modal/modalRouter' /* webpackChunkName: "secondary" */));
|
||||||
const Nag = lazyImport(() => import('component/common/nag' /* webpackChunkName: "secondary" */));
|
const Nag = lazyImport(() => import('component/common/nag' /* webpackChunkName: "secondary" */));
|
||||||
const NagContinueFirstRun = lazyImport(() =>
|
|
||||||
import('component/nagContinueFirstRun' /* webpackChunkName: "secondary" */)
|
|
||||||
);
|
|
||||||
const OpenInAppLink = lazyImport(() => import('web/component/openInAppLink' /* webpackChunkName: "secondary" */));
|
|
||||||
|
|
||||||
// @if TARGET='web'
|
|
||||||
const NagDataCollection = lazyImport(() =>
|
|
||||||
import('web/component/nag-data-collection' /* webpackChunkName: "secondary" */)
|
|
||||||
);
|
|
||||||
const NagDegradedPerformance = lazyImport(() =>
|
|
||||||
import('web/component/nag-degraded-performance' /* webpackChunkName: "secondary" */)
|
|
||||||
);
|
|
||||||
const NagNoUser = lazyImport(() => import('web/component/nag-no-user' /* webpackChunkName: "nag-no-user" */));
|
|
||||||
const NagSunset = lazyImport(() => import('web/component/nag-sunset' /* webpackChunkName: "nag-no-user" */));
|
|
||||||
const YoutubeWelcome = lazyImport(() =>
|
|
||||||
import('web/component/youtubeReferralWelcome' /* webpackChunkName: "secondary" */)
|
|
||||||
);
|
|
||||||
|
|
||||||
// @endif
|
|
||||||
|
|
||||||
const SyncFatalError = lazyImport(() => import('component/syncFatalError' /* webpackChunkName: "syncFatalError" */));
|
const SyncFatalError = lazyImport(() => import('component/syncFatalError' /* webpackChunkName: "syncFatalError" */));
|
||||||
const Yrbl = lazyImport(() => import('component/yrbl' /* webpackChunkName: "yrbl" */));
|
const Yrbl = lazyImport(() => import('component/yrbl' /* webpackChunkName: "yrbl" */));
|
||||||
|
@ -156,45 +123,26 @@ function App(props: Props) {
|
||||||
const isRewardApproved = user && user.is_reward_approved;
|
const isRewardApproved = user && user.is_reward_approved;
|
||||||
const previousHasVerifiedEmail = usePrevious(hasVerifiedEmail);
|
const previousHasVerifiedEmail = usePrevious(hasVerifiedEmail);
|
||||||
const previousRewardApproved = usePrevious(isRewardApproved);
|
const previousRewardApproved = usePrevious(isRewardApproved);
|
||||||
// @if TARGET='web'
|
const { pathname, search } = props.location;
|
||||||
const [showAnalyticsNag, setShowAnalyticsNag] = usePersistedState('analytics-nag', true);
|
|
||||||
const [lbryTvApiStatus, setLbryTvApiStatus] = useState(STATUS_OK);
|
|
||||||
// @endif
|
|
||||||
const { pathname, hash, search } = props.location;
|
|
||||||
const [upgradeNagClosed, setUpgradeNagClosed] = useState(false);
|
const [upgradeNagClosed, setUpgradeNagClosed] = useState(false);
|
||||||
const [resolvedSubscriptions, setResolvedSubscriptions] = useState(false);
|
const [resolvedSubscriptions, setResolvedSubscriptions] = useState(false);
|
||||||
const [sidebarOpen] = usePersistedState('sidebar', true);
|
const [sidebarOpen] = usePersistedState('sidebar', true);
|
||||||
const [seenSunsestMessage, setSeenSunsetMessage] = usePersistedState('lbrytv-sunset', false);
|
|
||||||
const showUpgradeButton =
|
const showUpgradeButton =
|
||||||
(autoUpdateDownloaded || (process.platform === 'linux' && isUpgradeAvailable)) && !upgradeNagClosed;
|
(autoUpdateDownloaded || (process.platform === 'linux' && isUpgradeAvailable)) && !upgradeNagClosed;
|
||||||
// referral claiming
|
// referral claiming
|
||||||
const referredRewardAvailable = rewards && rewards.some((reward) => reward.reward_type === REWARDS.TYPE_REFEREE);
|
const referredRewardAvailable = rewards && rewards.some((reward) => reward.reward_type === REWARDS.TYPE_REFEREE);
|
||||||
const urlParams = new URLSearchParams(search);
|
const urlParams = new URLSearchParams(search);
|
||||||
const rawReferrerParam = urlParams.get('r');
|
const rawReferrerParam = urlParams.get('r');
|
||||||
const fromLbrytvParam = urlParams.get('sunset');
|
|
||||||
const sanitizedReferrerParam = rawReferrerParam && rawReferrerParam.replace(':', '#');
|
const sanitizedReferrerParam = rawReferrerParam && rawReferrerParam.replace(':', '#');
|
||||||
const shouldHideNag = pathname.startsWith(`/$/${PAGES.EMBED}`) || pathname.startsWith(`/$/${PAGES.AUTH_VERIFY}`);
|
|
||||||
const userId = user && user.id;
|
const userId = user && user.id;
|
||||||
const useCustomScrollbar = !IS_MAC;
|
const useCustomScrollbar = !IS_MAC;
|
||||||
const hasMyChannels = myChannelUrls && myChannelUrls.length > 0;
|
const hasMyChannels = myChannelUrls && myChannelUrls.length > 0;
|
||||||
const hasNoChannels = myChannelUrls && myChannelUrls.length === 0;
|
const hasNoChannels = myChannelUrls && myChannelUrls.length === 0;
|
||||||
const shouldMigrateLanguage = LANGUAGE_MIGRATIONS[language];
|
const shouldMigrateLanguage = LANGUAGE_MIGRATIONS[language];
|
||||||
const hasActiveChannelClaim = activeChannelClaim !== undefined;
|
const hasActiveChannelClaim = activeChannelClaim !== undefined;
|
||||||
const isPersonalized = !IS_WEB || hasVerifiedEmail;
|
const isPersonalized = hasVerifiedEmail;
|
||||||
const renderFiledrop = !IS_WEB || isAuthenticated;
|
const renderFiledrop = isAuthenticated;
|
||||||
|
|
||||||
let uri;
|
|
||||||
try {
|
|
||||||
const newpath = buildURI(parseURI(pathname.slice(1).replace(/:/g, '#')));
|
|
||||||
uri = newpath + hash;
|
|
||||||
} catch (e) {}
|
|
||||||
|
|
||||||
// @if TARGET='web'
|
|
||||||
function handleAnalyticsDismiss() {
|
|
||||||
setShowAnalyticsNag(false);
|
|
||||||
}
|
|
||||||
|
|
||||||
// @endif
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (userId) {
|
if (userId) {
|
||||||
analytics.setUser(userId);
|
analytics.setUser(userId);
|
||||||
|
@ -325,23 +273,6 @@ function App(props: Props) {
|
||||||
}
|
}
|
||||||
}, [previousRewardApproved, isRewardApproved]);
|
}, [previousRewardApproved, isRewardApproved]);
|
||||||
|
|
||||||
// Load IMA3 SDK for aniview: DISABLED FOR NOW
|
|
||||||
// @if TARGET='web'
|
|
||||||
// useEffect(() => {
|
|
||||||
// if (ENABLE_PREROLL_ADS) {
|
|
||||||
// const script = document.createElement('script');
|
|
||||||
// script.src = `https://imasdk.googleapis.com/js/sdkloader/ima3.js`;
|
|
||||||
// script.async = true;
|
|
||||||
// // $FlowFixMe
|
|
||||||
// document.body.appendChild(script);
|
|
||||||
// return () => {
|
|
||||||
// // $FlowFixMe
|
|
||||||
// document.body.removeChild(script);
|
|
||||||
// };
|
|
||||||
// }
|
|
||||||
// });
|
|
||||||
// @endif
|
|
||||||
|
|
||||||
// @if TARGET='app'
|
// @if TARGET='app'
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (updatePreferences && getWalletSyncPref && readyForPrefs) {
|
if (updatePreferences && getWalletSyncPref && readyForPrefs) {
|
||||||
|
@ -357,19 +288,10 @@ function App(props: Props) {
|
||||||
// ready for sync syncs, however after signin when hasVerifiedEmail, that syncs too.
|
// ready for sync syncs, however after signin when hasVerifiedEmail, that syncs too.
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
// signInSyncPref is cleared after sharedState loop.
|
// signInSyncPref is cleared after sharedState loop.
|
||||||
const syncLoopWithoutInterval = () => syncLoop(true);
|
|
||||||
if (readyForSync && hasVerifiedEmail) {
|
if (readyForSync && hasVerifiedEmail) {
|
||||||
// In case we are syncing.
|
// In case we are syncing.
|
||||||
syncLoop();
|
syncLoop();
|
||||||
// @if TARGET='web'
|
|
||||||
window.addEventListener('focus', syncLoopWithoutInterval);
|
|
||||||
// @endif
|
|
||||||
}
|
}
|
||||||
// @if TARGET='web'
|
|
||||||
return () => {
|
|
||||||
window.removeEventListener('focus', syncLoopWithoutInterval);
|
|
||||||
};
|
|
||||||
// @endif
|
|
||||||
}, [readyForSync, hasVerifiedEmail, syncLoop]);
|
}, [readyForSync, hasVerifiedEmail, syncLoop]);
|
||||||
|
|
||||||
// We know someone is logging in or not when we get their user object
|
// We know someone is logging in or not when we get their user object
|
||||||
|
@ -407,31 +329,10 @@ function App(props: Props) {
|
||||||
}
|
}
|
||||||
}, [sidebarOpen, isPersonalized, resolvedSubscriptions, subscriptions, resolveUris, setResolvedSubscriptions]);
|
}, [sidebarOpen, isPersonalized, resolvedSubscriptions, subscriptions, resolveUris, setResolvedSubscriptions]);
|
||||||
|
|
||||||
// @if TARGET='web'
|
|
||||||
useDegradedPerformance(setLbryTvApiStatus, user);
|
|
||||||
// @endif
|
|
||||||
|
|
||||||
// @if TARGET='web'
|
|
||||||
// Require an internal-api user on lbry.tv
|
|
||||||
// This also prevents the site from loading in the un-authed state while we wait for internal-apis to return for the first time
|
|
||||||
// It's not needed on desktop since there is no un-authed state
|
|
||||||
if (user === undefined) {
|
|
||||||
return (
|
|
||||||
<div className="main--empty">
|
|
||||||
<Spinner delayed />
|
|
||||||
</div>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
// @endif
|
|
||||||
|
|
||||||
if (syncFatalError) {
|
if (syncFatalError) {
|
||||||
return (
|
return (
|
||||||
<React.Suspense fallback={null}>
|
<React.Suspense fallback={null}>
|
||||||
<SyncFatalError
|
<SyncFatalError />
|
||||||
// @if TARGET='web'
|
|
||||||
lbryTvApiStatus={lbryTvApiStatus}
|
|
||||||
// @endif
|
|
||||||
/>
|
|
||||||
</React.Suspense>
|
</React.Suspense>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
@ -447,16 +348,6 @@ function App(props: Props) {
|
||||||
ref={appRef}
|
ref={appRef}
|
||||||
onContextMenu={IS_WEB ? undefined : (e) => openContextMenu(e)}
|
onContextMenu={IS_WEB ? undefined : (e) => openContextMenu(e)}
|
||||||
>
|
>
|
||||||
{IS_WEB && lbryTvApiStatus === STATUS_DOWN ? (
|
|
||||||
<React.Suspense fallback={null}>
|
|
||||||
<Yrbl
|
|
||||||
className="main--empty"
|
|
||||||
title={__('lbry.tv is currently down')}
|
|
||||||
subtitle={__('My wheel broke, but the good news is that someone from LBRY is working on it.')}
|
|
||||||
/>
|
|
||||||
</React.Suspense>
|
|
||||||
) : (
|
|
||||||
<React.Fragment>
|
|
||||||
<Router />
|
<Router />
|
||||||
<React.Suspense fallback={null}>
|
<React.Suspense fallback={null}>
|
||||||
<ModalRouter />
|
<ModalRouter />
|
||||||
|
@ -476,25 +367,7 @@ function App(props: Props) {
|
||||||
/>
|
/>
|
||||||
)}
|
)}
|
||||||
{/* @endif */}
|
{/* @endif */}
|
||||||
|
|
||||||
{/* @if TARGET='web' */}
|
|
||||||
<YoutubeWelcome />
|
|
||||||
{!SIMPLE_SITE && !shouldHideNag && <OpenInAppLink uri={uri} />}
|
|
||||||
{!shouldHideNag && <NagContinueFirstRun />}
|
|
||||||
{fromLbrytvParam && !seenSunsestMessage && !shouldHideNag && (
|
|
||||||
<NagSunset email={hasVerifiedEmail} onClose={() => setSeenSunsetMessage(true)} />
|
|
||||||
)}
|
|
||||||
{(lbryTvApiStatus === STATUS_DEGRADED || lbryTvApiStatus === STATUS_FAILING) && !shouldHideNag && (
|
|
||||||
<NagDegradedPerformance onClose={() => setLbryTvApiStatus(STATUS_OK)} />
|
|
||||||
)}
|
|
||||||
{!SIMPLE_SITE && lbryTvApiStatus === STATUS_OK && showAnalyticsNag && !shouldHideNag && (
|
|
||||||
<NagDataCollection onClose={handleAnalyticsDismiss} />
|
|
||||||
)}
|
|
||||||
{user === null && <NagNoUser />}
|
|
||||||
{/* @endif */}
|
|
||||||
</React.Suspense>
|
</React.Suspense>
|
||||||
</React.Fragment>
|
|
||||||
)}
|
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,11 +1,8 @@
|
||||||
// @flow
|
// @flow
|
||||||
import { SIMPLE_SITE } from 'config';
|
|
||||||
import React, { Fragment } from 'react';
|
import React, { Fragment } from 'react';
|
||||||
import MarkdownPreview from 'component/common/markdown-preview';
|
import MarkdownPreview from 'component/common/markdown-preview';
|
||||||
import ClaimTags from 'component/claimTags';
|
import ClaimTags from 'component/claimTags';
|
||||||
import CreditAmount from 'component/common/credit-amount';
|
import CreditAmount from 'component/common/credit-amount';
|
||||||
import Button from 'component/button';
|
|
||||||
import * as PAGES from 'constants/pages';
|
|
||||||
import DateTime from 'component/dateTime';
|
import DateTime from 'component/dateTime';
|
||||||
import YoutubeBadge from 'component/youtubeBadge';
|
import YoutubeBadge from 'component/youtubeBadge';
|
||||||
import SUPPORTED_LANGUAGES from 'constants/supported_languages';
|
import SUPPORTED_LANGUAGES from 'constants/supported_languages';
|
||||||
|
@ -101,15 +98,6 @@ function ChannelAbout(props: Props) {
|
||||||
amount={parseFloat(claim.amount) + parseFloat(claim.meta.support_amount)}
|
amount={parseFloat(claim.amount) + parseFloat(claim.meta.support_amount)}
|
||||||
precision={8}
|
precision={8}
|
||||||
/>{' '}
|
/>{' '}
|
||||||
{SIMPLE_SITE && (
|
|
||||||
<Button
|
|
||||||
button="link"
|
|
||||||
label={__('view other claims at lbry://%name%', {
|
|
||||||
name: claim.name,
|
|
||||||
})}
|
|
||||||
navigate={`/$/${PAGES.TOP}?name=${claim.name}`}
|
|
||||||
/>
|
|
||||||
)}
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<YoutubeBadge channelClaimId={claimId} />
|
<YoutubeBadge channelClaimId={claimId} />
|
||||||
|
|
|
@ -1,5 +1,4 @@
|
||||||
// @flow
|
// @flow
|
||||||
import { SHOW_ADS, SIMPLE_SITE } from 'config';
|
|
||||||
import * as CS from 'constants/claim_search';
|
import * as CS from 'constants/claim_search';
|
||||||
import * as ICONS from 'constants/icons';
|
import * as ICONS from 'constants/icons';
|
||||||
import React, { Fragment } from 'react';
|
import React, { Fragment } from 'react';
|
||||||
|
@ -7,7 +6,6 @@ import HiddenNsfwClaims from 'component/hiddenNsfwClaims';
|
||||||
import { useHistory } from 'react-router-dom';
|
import { useHistory } from 'react-router-dom';
|
||||||
import Button from 'component/button';
|
import Button from 'component/button';
|
||||||
import ClaimListDiscover from 'component/claimListDiscover';
|
import ClaimListDiscover from 'component/claimListDiscover';
|
||||||
import Ads from 'web/component/ads';
|
|
||||||
import Icon from 'component/common/icon';
|
import Icon from 'component/common/icon';
|
||||||
import LivestreamLink from 'component/livestreamLink';
|
import LivestreamLink from 'component/livestreamLink';
|
||||||
import { Form, FormField } from 'component/common/form';
|
import { Form, FormField } from 'component/common/form';
|
||||||
|
@ -46,7 +44,6 @@ function ChannelContent(props: Props) {
|
||||||
channelIsBlocked,
|
channelIsBlocked,
|
||||||
channelIsBlackListed,
|
channelIsBlackListed,
|
||||||
claim,
|
claim,
|
||||||
isAuthenticated,
|
|
||||||
defaultPageSize = CS.PAGE_SIZE,
|
defaultPageSize = CS.PAGE_SIZE,
|
||||||
defaultInfiniteScroll = true,
|
defaultInfiniteScroll = true,
|
||||||
showMature,
|
showMature,
|
||||||
|
@ -152,14 +149,12 @@ function ChannelContent(props: Props) {
|
||||||
hideAdvancedFilter={!showFilters}
|
hideAdvancedFilter={!showFilters}
|
||||||
tileLayout={tileLayout}
|
tileLayout={tileLayout}
|
||||||
uris={searchResults}
|
uris={searchResults}
|
||||||
streamType={SIMPLE_SITE ? CS.CONTENT_ALL : undefined}
|
|
||||||
channelIds={[claimId]}
|
channelIds={[claimId]}
|
||||||
claimType={claimType}
|
claimType={claimType}
|
||||||
feeAmount={CS.FEE_AMOUNT_ANY}
|
feeAmount={CS.FEE_AMOUNT_ANY}
|
||||||
defaultOrderBy={CS.ORDER_BY_NEW}
|
defaultOrderBy={CS.ORDER_BY_NEW}
|
||||||
pageSize={defaultPageSize}
|
pageSize={defaultPageSize}
|
||||||
infiniteScroll={defaultInfiniteScroll}
|
infiniteScroll={defaultInfiniteScroll}
|
||||||
injectedItem={SHOW_ADS && !isAuthenticated && IS_WEB && <Ads type="video" />}
|
|
||||||
meta={
|
meta={
|
||||||
showFilters && (
|
showFilters && (
|
||||||
<Form onSubmit={() => {}} className="wunderbar--inline">
|
<Form onSubmit={() => {}} className="wunderbar--inline">
|
||||||
|
|
|
@ -20,7 +20,6 @@ import analytics from 'analytics';
|
||||||
import LbcSymbol from 'component/common/lbc-symbol';
|
import LbcSymbol from 'component/common/lbc-symbol';
|
||||||
import SUPPORTED_LANGUAGES from 'constants/supported_languages';
|
import SUPPORTED_LANGUAGES from 'constants/supported_languages';
|
||||||
import WalletSpendableBalanceHelp from 'component/walletSpendableBalanceHelp';
|
import WalletSpendableBalanceHelp from 'component/walletSpendableBalanceHelp';
|
||||||
import { SIMPLE_SITE } from 'config';
|
|
||||||
import { sortLanguageMap } from 'util/default-languages';
|
import { sortLanguageMap } from 'util/default-languages';
|
||||||
import ThumbnailBrokenImage from 'component/selectThumbnail/thumbnail-broken.png';
|
import ThumbnailBrokenImage from 'component/selectThumbnail/thumbnail-broken.png';
|
||||||
import Gerbil from 'component/channelThumbnail/gerbil.png';
|
import Gerbil from 'component/channelThumbnail/gerbil.png';
|
||||||
|
@ -424,7 +423,7 @@ function ChannelForm(props: Props) {
|
||||||
<Card
|
<Card
|
||||||
body={
|
body={
|
||||||
<TagsSearch
|
<TagsSearch
|
||||||
suggestMature={!SIMPLE_SITE}
|
suggestMature
|
||||||
disableAutoFocus
|
disableAutoFocus
|
||||||
disableControlTags
|
disableControlTags
|
||||||
limitSelect={MAX_TAG_SELECT}
|
limitSelect={MAX_TAG_SELECT}
|
||||||
|
|
|
@ -1,6 +1,5 @@
|
||||||
// @flow
|
// @flow
|
||||||
import { INLINE_PLAYER_WRAPPER_CLASS } from 'component/fileRenderFloating/view';
|
import { INLINE_PLAYER_WRAPPER_CLASS } from 'component/fileRenderFloating/view';
|
||||||
import { SIMPLE_SITE } from 'config';
|
|
||||||
import * as React from 'react';
|
import * as React from 'react';
|
||||||
import Button from 'component/button';
|
import Button from 'component/button';
|
||||||
import classnames from 'classnames';
|
import classnames from 'classnames';
|
||||||
|
@ -110,13 +109,7 @@ class ClaimLink extends React.Component<Props> {
|
||||||
<Button button="link" className="preview-link__url" label={uri} navigate={uri} />
|
<Button button="link" className="preview-link__url" label={uri} navigate={uri} />
|
||||||
</div>
|
</div>
|
||||||
) : (
|
) : (
|
||||||
<Button
|
<Button button="link" title={children} label={children} className="button--external-link" navigate={uri} />
|
||||||
button="link"
|
|
||||||
title={SIMPLE_SITE ? __("This channel isn't staking enough LBRY Credits for link previews.") : children}
|
|
||||||
label={children}
|
|
||||||
className="button--external-link"
|
|
||||||
navigate={uri}
|
|
||||||
/>
|
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
// @flow
|
// @flow
|
||||||
import { ENABLE_NO_SOURCE_CLAIMS, SIMPLE_SITE } from 'config';
|
import { ENABLE_NO_SOURCE_CLAIMS } from 'config';
|
||||||
import type { Node } from 'react';
|
import type { Node } from 'react';
|
||||||
import * as CS from 'constants/claim_search';
|
import * as CS from 'constants/claim_search';
|
||||||
import React from 'react';
|
import React from 'react';
|
||||||
|
@ -125,8 +125,8 @@ function ClaimListDiscover(props: Props) {
|
||||||
claimType,
|
claimType,
|
||||||
pageSize,
|
pageSize,
|
||||||
defaultClaimType,
|
defaultClaimType,
|
||||||
streamType = SIMPLE_SITE ? [CS.FILE_VIDEO, CS.FILE_AUDIO] : undefined,
|
streamType,
|
||||||
defaultStreamType = SIMPLE_SITE ? CS.FILE_VIDEO : undefined, // add param for DEFAULT_STREAM_TYPE
|
defaultStreamType, // add param for DEFAULT_STREAM_TYPE
|
||||||
freshness,
|
freshness,
|
||||||
defaultFreshness = CS.FRESH_WEEK,
|
defaultFreshness = CS.FRESH_WEEK,
|
||||||
renderProperties,
|
renderProperties,
|
||||||
|
|
|
@ -8,7 +8,7 @@ import { doFetchViewCount } from 'lbryinc';
|
||||||
import { doToggleTagFollowDesktop } from 'redux/actions/tags';
|
import { doToggleTagFollowDesktop } from 'redux/actions/tags';
|
||||||
import { makeSelectClientSetting, selectShowMatureContent } from 'redux/selectors/settings';
|
import { makeSelectClientSetting, selectShowMatureContent } from 'redux/selectors/settings';
|
||||||
import { selectMutedAndBlockedChannelIds } from 'redux/selectors/blocked';
|
import { selectMutedAndBlockedChannelIds } from 'redux/selectors/blocked';
|
||||||
import { ENABLE_NO_SOURCE_CLAIMS, SIMPLE_SITE } from 'config';
|
import { ENABLE_NO_SOURCE_CLAIMS } from 'config';
|
||||||
import * as CS from 'constants/claim_search';
|
import * as CS from 'constants/claim_search';
|
||||||
|
|
||||||
import ClaimListDiscover from './view';
|
import ClaimListDiscover from './view';
|
||||||
|
@ -68,7 +68,7 @@ function resolveSearchOptions(props) {
|
||||||
let streamTypesParam;
|
let streamTypesParam;
|
||||||
if (streamTypes) {
|
if (streamTypes) {
|
||||||
streamTypesParam = streamTypes;
|
streamTypesParam = streamTypes;
|
||||||
} else if (SIMPLE_SITE && !hasNoSource && streamTypes !== null) {
|
} else if (!hasNoSource && streamTypes !== null) {
|
||||||
streamTypesParam = [CS.FILE_VIDEO, CS.FILE_AUDIO];
|
streamTypesParam = [CS.FILE_VIDEO, CS.FILE_AUDIO];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -5,7 +5,7 @@ import * as KEYCODES from 'constants/keycodes';
|
||||||
import { COMMENT_HIGHLIGHTED } from 'constants/classnames';
|
import { COMMENT_HIGHLIGHTED } from 'constants/classnames';
|
||||||
import { SORT_BY, COMMENT_PAGE_SIZE_REPLIES } from 'constants/comment';
|
import { SORT_BY, COMMENT_PAGE_SIZE_REPLIES } from 'constants/comment';
|
||||||
import { FF_MAX_CHARS_IN_COMMENT } from 'constants/form-field';
|
import { FF_MAX_CHARS_IN_COMMENT } from 'constants/form-field';
|
||||||
import { SITE_NAME, SIMPLE_SITE, ENABLE_COMMENT_REACTIONS } from 'config';
|
import { SITE_NAME, ENABLE_COMMENT_REACTIONS } from 'config';
|
||||||
import React, { useEffect, useState } from 'react';
|
import React, { useEffect, useState } from 'react';
|
||||||
import { parseURI } from 'util/lbryURI';
|
import { parseURI } from 'util/lbryURI';
|
||||||
import DateTime from 'component/dateTime';
|
import DateTime from 'component/dateTime';
|
||||||
|
@ -180,7 +180,7 @@ function Comment(props: Props) {
|
||||||
}, [page, uri, commentId, fetchReplies]);
|
}, [page, uri, commentId, fetchReplies]);
|
||||||
|
|
||||||
function handleEditMessageChanged(event) {
|
function handleEditMessageChanged(event) {
|
||||||
setCommentValue(!SIMPLE_SITE && advancedEditor ? event : event.target.value);
|
setCommentValue(advancedEditor ? event : event.target.value);
|
||||||
}
|
}
|
||||||
|
|
||||||
function handleEditComment() {
|
function handleEditComment() {
|
||||||
|
@ -306,7 +306,7 @@ function Comment(props: Props) {
|
||||||
<Form onSubmit={handleSubmit}>
|
<Form onSubmit={handleSubmit}>
|
||||||
<FormField
|
<FormField
|
||||||
className="comment__edit-input"
|
className="comment__edit-input"
|
||||||
type={!SIMPLE_SITE && advancedEditor ? 'markdown' : 'textarea'}
|
type={advancedEditor ? 'markdown' : 'textarea'}
|
||||||
name="editing_comment"
|
name="editing_comment"
|
||||||
value={editedMessage}
|
value={editedMessage}
|
||||||
charCount={charCount}
|
charCount={charCount}
|
||||||
|
|
|
@ -3,7 +3,6 @@ import { FF_MAX_CHARS_IN_COMMENT, FF_MAX_CHARS_IN_LIVESTREAM_COMMENT } from 'con
|
||||||
import { FormField, Form } from 'component/common/form';
|
import { FormField, Form } from 'component/common/form';
|
||||||
import { getChannelIdFromClaim } from 'util/claim';
|
import { getChannelIdFromClaim } from 'util/claim';
|
||||||
import { Lbryio } from 'lbryinc';
|
import { Lbryio } from 'lbryinc';
|
||||||
import { SIMPLE_SITE } from 'config';
|
|
||||||
import { useHistory } from 'react-router';
|
import { useHistory } from 'react-router';
|
||||||
import * as ICONS from 'constants/icons';
|
import * as ICONS from 'constants/icons';
|
||||||
import * as KEYCODES from 'constants/keycodes';
|
import * as KEYCODES from 'constants/keycodes';
|
||||||
|
@ -170,7 +169,7 @@ export function CommentCreate(props: Props) {
|
||||||
if (isReply) {
|
if (isReply) {
|
||||||
commentValue = event.target.value;
|
commentValue = event.target.value;
|
||||||
} else {
|
} else {
|
||||||
commentValue = !SIMPLE_SITE && advancedEditor ? event : event.target.value;
|
commentValue = advancedEditor ? event : event.target.value;
|
||||||
}
|
}
|
||||||
|
|
||||||
setCommentValue(commentValue);
|
setCommentValue(commentValue);
|
||||||
|
@ -528,7 +527,7 @@ export function CommentCreate(props: Props) {
|
||||||
)}
|
)}
|
||||||
<FormField
|
<FormField
|
||||||
disabled={isFetchingChannels}
|
disabled={isFetchingChannels}
|
||||||
type={SIMPLE_SITE ? 'textarea' : advancedEditor && !isReply ? 'markdown' : 'textarea'}
|
type={'textarea'}
|
||||||
name={isReply ? 'content_reply' : 'content_description'}
|
name={isReply ? 'content_reply' : 'content_description'}
|
||||||
ref={formFieldRef}
|
ref={formFieldRef}
|
||||||
className={isReply ? 'content_reply' : 'content_comment'}
|
className={isReply ? 'content_reply' : 'content_comment'}
|
||||||
|
@ -540,10 +539,8 @@ export function CommentCreate(props: Props) {
|
||||||
<SelectChannel tiny />
|
<SelectChannel tiny />
|
||||||
</span>
|
</span>
|
||||||
}
|
}
|
||||||
quickActionLabel={
|
quickActionLabel={isReply ? undefined : advancedEditor ? __('Simple Editor') : __('Advanced Editor')}
|
||||||
!SIMPLE_SITE && (isReply ? undefined : advancedEditor ? __('Simple Editor') : __('Advanced Editor'))
|
quickActionHandler={() => setAdvancedEditor(!advancedEditor)}
|
||||||
}
|
|
||||||
quickActionHandler={() => !SIMPLE_SITE && setAdvancedEditor(!advancedEditor)}
|
|
||||||
onFocus={onTextareaFocus}
|
onFocus={onTextareaFocus}
|
||||||
onBlur={onTextareaBlur}
|
onBlur={onTextareaBlur}
|
||||||
placeholder={__('Say something about this...')}
|
placeholder={__('Say something about this...')}
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
// @flow
|
// @flow
|
||||||
import { ENABLE_CREATOR_REACTIONS, SIMPLE_SITE } from 'config';
|
import { ENABLE_CREATOR_REACTIONS } from 'config';
|
||||||
import * as ICONS from 'constants/icons';
|
import * as ICONS from 'constants/icons';
|
||||||
import * as PAGES from 'constants/pages';
|
import * as PAGES from 'constants/pages';
|
||||||
import * as REACTION_TYPES from 'constants/reactions';
|
import * as REACTION_TYPES from 'constants/reactions';
|
||||||
|
@ -72,16 +72,8 @@ export default function CommentReactions(props: Props) {
|
||||||
};
|
};
|
||||||
const shouldHide = !canCreatorReact && hideCreatorLike;
|
const shouldHide = !canCreatorReact && hideCreatorLike;
|
||||||
const creatorLiked = getCountForReact(REACTION_TYPES.CREATOR_LIKE) > 0;
|
const creatorLiked = getCountForReact(REACTION_TYPES.CREATOR_LIKE) > 0;
|
||||||
const likeIcon = SIMPLE_SITE
|
const likeIcon = ICONS.UPVOTE;
|
||||||
? myReacts.includes(REACTION_TYPES.LIKE)
|
const dislikeIcon = ICONS.DOWNVOTE;
|
||||||
? ICONS.FIRE_ACTIVE
|
|
||||||
: ICONS.FIRE
|
|
||||||
: ICONS.UPVOTE;
|
|
||||||
const dislikeIcon = SIMPLE_SITE
|
|
||||||
? myReacts.includes(REACTION_TYPES.DISLIKE)
|
|
||||||
? ICONS.SLIME_ACTIVE
|
|
||||||
: ICONS.SLIME
|
|
||||||
: ICONS.DOWNVOTE;
|
|
||||||
|
|
||||||
function handleCommentLike() {
|
function handleCommentLike() {
|
||||||
if (activeChannelId) {
|
if (activeChannelId) {
|
||||||
|
|
|
@ -13,7 +13,7 @@ import defaultSchema from 'hast-util-sanitize/lib/github.json';
|
||||||
import { formatedLinks, inlineLinks } from 'util/remark-lbry';
|
import { formatedLinks, inlineLinks } from 'util/remark-lbry';
|
||||||
import { formattedTimestamp, inlineTimestamp } from 'util/remark-timestamp';
|
import { formattedTimestamp, inlineTimestamp } from 'util/remark-timestamp';
|
||||||
import ZoomableImage from 'component/zoomableImage';
|
import ZoomableImage from 'component/zoomableImage';
|
||||||
import { CHANNEL_STAKED_LEVEL_VIDEO_COMMENTS, SIMPLE_SITE } from 'config';
|
import { CHANNEL_STAKED_LEVEL_VIDEO_COMMENTS } from 'config';
|
||||||
import Button from 'component/button';
|
import Button from 'component/button';
|
||||||
import * as ICONS from 'constants/icons';
|
import * as ICONS from 'constants/icons';
|
||||||
|
|
||||||
|
@ -171,16 +171,7 @@ const MarkdownPreview = (props: MarkdownProps) => {
|
||||||
div: React.Fragment,
|
div: React.Fragment,
|
||||||
img: isStakeEnoughForPreview(stakedLevel)
|
img: isStakeEnoughForPreview(stakedLevel)
|
||||||
? ZoomableImage
|
? ZoomableImage
|
||||||
: (imgProps) => (
|
: (imgProps) => <SimpleImageLink src={imgProps.src} alt={imgProps.alt} title={imgProps.title} />,
|
||||||
<SimpleImageLink
|
|
||||||
src={imgProps.src}
|
|
||||||
alt={imgProps.alt}
|
|
||||||
title={imgProps.title}
|
|
||||||
helpText={
|
|
||||||
SIMPLE_SITE ? __("This channel isn't staking enough LBRY Credits for inline image previews.") : ''
|
|
||||||
}
|
|
||||||
/>
|
|
||||||
),
|
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -35,12 +35,6 @@ class ErrorBoundary extends React.Component<Props, State> {
|
||||||
}
|
}
|
||||||
|
|
||||||
componentDidCatch(error, errorInfo) {
|
componentDidCatch(error, errorInfo) {
|
||||||
// @if TARGET='web'
|
|
||||||
analytics.sentryError(error, errorInfo).then((sentryEventId) => {
|
|
||||||
this.setState({ sentryEventId });
|
|
||||||
});
|
|
||||||
// @endif
|
|
||||||
|
|
||||||
// @if TARGET='app'
|
// @if TARGET='app'
|
||||||
let errorMessage = 'Uncaught error\n';
|
let errorMessage = 'Uncaught error\n';
|
||||||
Native.getAppVersionInfo().then(({ localVersion }) => {
|
Native.getAppVersionInfo().then(({ localVersion }) => {
|
||||||
|
@ -105,9 +99,6 @@ class ErrorBoundary extends React.Component<Props, State> {
|
||||||
|
|
||||||
{errorWasReported && (
|
{errorWasReported && (
|
||||||
<div className="error__wrapper">
|
<div className="error__wrapper">
|
||||||
{/* @if TARGET='web' */}
|
|
||||||
<span className="error__text">{__('Error ID: %sentryEventId%', { sentryEventId })}</span>
|
|
||||||
{/* @endif */}
|
|
||||||
{/* @if TARGET='app' */}
|
{/* @if TARGET='app' */}
|
||||||
<span className="error__text">{__('This error was reported and will be fixed.')}</span>
|
<span className="error__text">{__('This error was reported and will be fixed.')}</span>
|
||||||
{/* @endif */}
|
{/* @endif */}
|
||||||
|
|
|
@ -16,7 +16,6 @@ import { useHistory } from 'react-router';
|
||||||
import FileReactions from 'component/fileReactions';
|
import FileReactions from 'component/fileReactions';
|
||||||
import { Menu, MenuButton, MenuList, MenuItem } from '@reach/menu-button';
|
import { Menu, MenuButton, MenuList, MenuItem } from '@reach/menu-button';
|
||||||
import Icon from 'component/common/icon';
|
import Icon from 'component/common/icon';
|
||||||
import { webDownloadClaim } from 'util/downloadClaim';
|
|
||||||
|
|
||||||
type Props = {
|
type Props = {
|
||||||
uri: string,
|
uri: string,
|
||||||
|
@ -53,8 +52,6 @@ function FileActions(props: Props) {
|
||||||
hideRepost,
|
hideRepost,
|
||||||
isLivestreamClaim,
|
isLivestreamClaim,
|
||||||
reactionsDisabled,
|
reactionsDisabled,
|
||||||
download,
|
|
||||||
streamingUrl,
|
|
||||||
} = props;
|
} = props;
|
||||||
const {
|
const {
|
||||||
push,
|
push,
|
||||||
|
@ -67,7 +64,6 @@ function FileActions(props: Props) {
|
||||||
const claimId = claim && claim.claim_id;
|
const claimId = claim && claim.claim_id;
|
||||||
const { signing_channel: signingChannel } = claim;
|
const { signing_channel: signingChannel } = claim;
|
||||||
const channelName = signingChannel && signingChannel.name;
|
const channelName = signingChannel && signingChannel.name;
|
||||||
const fileName = claim && claim.value && claim.value.source && claim.value.source.name;
|
|
||||||
|
|
||||||
// We want to use the short form uri for editing
|
// We want to use the short form uri for editing
|
||||||
// This is what the user is used to seeing, they don't care about the claim id
|
// This is what the user is used to seeing, they don't care about the claim id
|
||||||
|
@ -88,23 +84,6 @@ function FileActions(props: Props) {
|
||||||
const urlParams = new URLSearchParams(search);
|
const urlParams = new URLSearchParams(search);
|
||||||
const collectionId = urlParams.get(COLLECTIONS_CONSTS.COLLECTION_ID);
|
const collectionId = urlParams.get(COLLECTIONS_CONSTS.COLLECTION_ID);
|
||||||
|
|
||||||
// @if TARGET='web'
|
|
||||||
const [downloadClicked, setDownloadClicked] = React.useState(false);
|
|
||||||
|
|
||||||
function handleWebDownload() {
|
|
||||||
// download() causes 'streamingUrl' to be populated.
|
|
||||||
download(uri);
|
|
||||||
setDownloadClicked(true);
|
|
||||||
}
|
|
||||||
|
|
||||||
React.useEffect(() => {
|
|
||||||
if (downloadClicked && streamingUrl) {
|
|
||||||
webDownloadClaim(streamingUrl, fileName);
|
|
||||||
setDownloadClicked(false);
|
|
||||||
}
|
|
||||||
}, [downloadClicked, streamingUrl, fileName]);
|
|
||||||
// @endif
|
|
||||||
|
|
||||||
function handleRepostClick() {
|
function handleRepostClick() {
|
||||||
if (!hasChannels) {
|
if (!hasChannels) {
|
||||||
clearPlayingUri();
|
clearPlayingUri();
|
||||||
|
@ -180,16 +159,6 @@ function FileActions(props: Props) {
|
||||||
<Icon size={20} icon={ICONS.MORE} />
|
<Icon size={20} icon={ICONS.MORE} />
|
||||||
</MenuButton>
|
</MenuButton>
|
||||||
<MenuList className="menu__list">
|
<MenuList className="menu__list">
|
||||||
{/* @if TARGET='web' */}
|
|
||||||
{!isLivestreamClaim && (
|
|
||||||
<MenuItem className="comment__menu-option" onSelect={handleWebDownload}>
|
|
||||||
<div className="menu__link">
|
|
||||||
<Icon aria-hidden icon={ICONS.DOWNLOAD} />
|
|
||||||
{__('Download')}
|
|
||||||
</div>
|
|
||||||
</MenuItem>
|
|
||||||
)}
|
|
||||||
{/* @endif */}
|
|
||||||
{!claimIsMine && (
|
{!claimIsMine && (
|
||||||
<MenuItem
|
<MenuItem
|
||||||
className="comment__menu-option"
|
className="comment__menu-option"
|
||||||
|
|
|
@ -1,5 +1,4 @@
|
||||||
// @flow
|
// @flow
|
||||||
import { SIMPLE_SITE } from 'config';
|
|
||||||
import React, { PureComponent } from 'react';
|
import React, { PureComponent } from 'react';
|
||||||
import Button from 'component/button';
|
import Button from 'component/button';
|
||||||
import path from 'path';
|
import path from 'path';
|
||||||
|
@ -49,7 +48,6 @@ class FileDetails extends PureComponent<Props> {
|
||||||
<span>{claim.claim_id}</span>
|
<span>{claim.claim_id}</span>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
{!SIMPLE_SITE && (
|
|
||||||
<>
|
<>
|
||||||
{languages && (
|
{languages && (
|
||||||
<div className="media__details">
|
<div className="media__details">
|
||||||
|
@ -88,7 +86,6 @@ class FileDetails extends PureComponent<Props> {
|
||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
</>
|
</>
|
||||||
)}
|
|
||||||
|
|
||||||
{fileSize && (
|
{fileSize && (
|
||||||
<div className="media__details">
|
<div className="media__details">
|
||||||
|
|
|
@ -1,9 +1,8 @@
|
||||||
// @flow
|
// @flow
|
||||||
import * as ICONS from 'constants/icons';
|
import * as ICONS from 'constants/icons';
|
||||||
import * as MODALS from 'constants/modal_types';
|
import * as MODALS from 'constants/modal_types';
|
||||||
import React, { useState } from 'react';
|
import React from 'react';
|
||||||
import Button from 'component/button';
|
import Button from 'component/button';
|
||||||
import { webDownloadClaim } from 'util/downloadClaim';
|
|
||||||
|
|
||||||
type Props = {
|
type Props = {
|
||||||
uri: string,
|
uri: string,
|
||||||
|
@ -40,23 +39,9 @@ function FileDownloadLink(props: Props) {
|
||||||
showLabel = false,
|
showLabel = false,
|
||||||
hideOpenButton = false,
|
hideOpenButton = false,
|
||||||
hideDownloadStatus = false,
|
hideDownloadStatus = false,
|
||||||
streamingUrl,
|
|
||||||
} = props;
|
} = props;
|
||||||
|
|
||||||
const [didClickDownloadButton, setDidClickDownloadButton] = useState(false);
|
|
||||||
const fileName = claim && claim.value && claim.value.source && claim.value.source.name;
|
|
||||||
|
|
||||||
// @if TARGET='web'
|
|
||||||
React.useEffect(() => {
|
|
||||||
if (didClickDownloadButton && streamingUrl) {
|
|
||||||
webDownloadClaim(streamingUrl, fileName);
|
|
||||||
setDidClickDownloadButton(false);
|
|
||||||
}
|
|
||||||
}, [streamingUrl, didClickDownloadButton, fileName]);
|
|
||||||
// @endif
|
|
||||||
|
|
||||||
function handleDownload(e) {
|
function handleDownload(e) {
|
||||||
setDidClickDownloadButton(true);
|
|
||||||
e.preventDefault();
|
e.preventDefault();
|
||||||
download(uri);
|
download(uri);
|
||||||
}
|
}
|
||||||
|
|
|
@ -6,7 +6,6 @@ import classnames from 'classnames';
|
||||||
import Button from 'component/button';
|
import Button from 'component/button';
|
||||||
import { formatNumberWithCommas } from 'util/number';
|
import { formatNumberWithCommas } from 'util/number';
|
||||||
import NudgeFloating from 'component/nudgeFloating';
|
import NudgeFloating from 'component/nudgeFloating';
|
||||||
import { SIMPLE_SITE } from 'config';
|
|
||||||
|
|
||||||
type Props = {
|
type Props = {
|
||||||
claim: StreamClaim,
|
claim: StreamClaim,
|
||||||
|
@ -36,12 +35,8 @@ function FileReactions(props: Props) {
|
||||||
const claimId = claim && claim.claim_id;
|
const claimId = claim && claim.claim_id;
|
||||||
const channel = claim && claim.signing_channel && claim.signing_channel.name;
|
const channel = claim && claim.signing_channel && claim.signing_channel.name;
|
||||||
const isCollection = claim && claim.value_type === 'collection'; // hack because nudge gets cut off by card on cols.
|
const isCollection = claim && claim.value_type === 'collection'; // hack because nudge gets cut off by card on cols.
|
||||||
const likeIcon = SIMPLE_SITE ? (myReaction === REACTION_TYPES.LIKE ? ICONS.FIRE_ACTIVE : ICONS.FIRE) : ICONS.UPVOTE;
|
const likeIcon = ICONS.UPVOTE;
|
||||||
const dislikeIcon = SIMPLE_SITE
|
const dislikeIcon = ICONS.DOWNVOTE;
|
||||||
? myReaction === REACTION_TYPES.DISLIKE
|
|
||||||
? ICONS.SLIME_ACTIVE
|
|
||||||
: ICONS.SLIME
|
|
||||||
: ICONS.DOWNVOTE;
|
|
||||||
React.useEffect(() => {
|
React.useEffect(() => {
|
||||||
function fetchReactions() {
|
function fetchReactions() {
|
||||||
doFetchReactions(claimId);
|
doFetchReactions(claimId);
|
||||||
|
@ -74,25 +69,24 @@ function FileReactions(props: Props) {
|
||||||
|
|
||||||
<Button
|
<Button
|
||||||
title={__('I like this')}
|
title={__('I like this')}
|
||||||
requiresAuth={IS_WEB}
|
|
||||||
authSrc="filereaction_like"
|
authSrc="filereaction_like"
|
||||||
className={classnames('button--file-action', {
|
className={classnames('button--file-action', {
|
||||||
'button--fire': SIMPLE_SITE && myReaction === REACTION_TYPES.LIKE,
|
'button--file-action-active': myReaction === REACTION_TYPES.LIKE,
|
||||||
'button--file-action-active': !SIMPLE_SITE && myReaction === REACTION_TYPES.LIKE,
|
|
||||||
})}
|
})}
|
||||||
label={
|
label={
|
||||||
<>
|
<>
|
||||||
{myReaction === REACTION_TYPES.LIKE && SIMPLE_SITE && (
|
{/* Be nice to have animated Likes */}
|
||||||
<>
|
{/* {myReaction === REACTION_TYPES.LIKE && SIMPLE_SITE && ( */}
|
||||||
<div className="button__fire-glow" />
|
{/* <> */}
|
||||||
<div className="button__fire-particle1" />
|
{/* <div className="button__fire-glow" /> */}
|
||||||
<div className="button__fire-particle2" />
|
{/* <div className="button__fire-particle1" /> */}
|
||||||
<div className="button__fire-particle3" />
|
{/* <div className="button__fire-particle2" /> */}
|
||||||
<div className="button__fire-particle4" />
|
{/* <div className="button__fire-particle3" /> */}
|
||||||
<div className="button__fire-particle5" />
|
{/* <div className="button__fire-particle4" /> */}
|
||||||
<div className="button__fire-particle6" />
|
{/* <div className="button__fire-particle5" /> */}
|
||||||
</>
|
{/* <div className="button__fire-particle6" /> */}
|
||||||
)}
|
{/* </> */}
|
||||||
|
{/* )} */}
|
||||||
{formatNumberWithCommas(likeCount, 0)}
|
{formatNumberWithCommas(likeCount, 0)}
|
||||||
</>
|
</>
|
||||||
}
|
}
|
||||||
|
@ -104,22 +98,8 @@ function FileReactions(props: Props) {
|
||||||
requiresAuth={IS_WEB}
|
requiresAuth={IS_WEB}
|
||||||
authSrc={'filereaction_dislike'}
|
authSrc={'filereaction_dislike'}
|
||||||
title={__('I dislike this')}
|
title={__('I dislike this')}
|
||||||
className={classnames('button--file-action', {
|
className={classnames('button--file-action', { 'button--file-action-active': myReaction === REACTION_TYPES.DISLIKE })}
|
||||||
'button--slime': SIMPLE_SITE && myReaction === REACTION_TYPES.DISLIKE,
|
label={<>{formatNumberWithCommas(dislikeCount, 0)}</>}
|
||||||
'button--file-action-active': !SIMPLE_SITE && myReaction === REACTION_TYPES.DISLIKE,
|
|
||||||
})}
|
|
||||||
label={
|
|
||||||
<>
|
|
||||||
{myReaction === REACTION_TYPES.DISLIKE && SIMPLE_SITE && (
|
|
||||||
<>
|
|
||||||
<div className="button__slime-stain" />
|
|
||||||
<div className="button__slime-drop1" />
|
|
||||||
<div className="button__slime-drop2" />
|
|
||||||
</>
|
|
||||||
)}
|
|
||||||
{formatNumberWithCommas(dislikeCount, 0)}
|
|
||||||
</>
|
|
||||||
}
|
|
||||||
iconSize={18}
|
iconSize={18}
|
||||||
icon={dislikeIcon}
|
icon={dislikeIcon}
|
||||||
onClick={() => doReactionDislike(uri)}
|
onClick={() => doReactionDislike(uri)}
|
||||||
|
|
|
@ -1,5 +1,4 @@
|
||||||
// @flow
|
// @flow
|
||||||
import { SIMPLE_SITE } from 'config';
|
|
||||||
import React from 'react';
|
import React from 'react';
|
||||||
import HelpLink from 'component/common/help-link';
|
import HelpLink from 'component/common/help-link';
|
||||||
|
|
||||||
|
@ -16,7 +15,7 @@ type Props = {
|
||||||
};
|
};
|
||||||
|
|
||||||
function FileViewCount(props: Props) {
|
function FileViewCount(props: Props) {
|
||||||
const { claim, uri, fetchViewCount, viewCount, livestream, activeViewers, isLive = false, doAnalyticsView } = props;
|
const { claim, uri, fetchViewCount, viewCount, livestream, activeViewers, doAnalyticsView } = props;
|
||||||
const claimId = claim && claim.claim_id;
|
const claimId = claim && claim.claim_id;
|
||||||
|
|
||||||
React.useEffect(() => {
|
React.useEffect(() => {
|
||||||
|
@ -37,15 +36,10 @@ function FileViewCount(props: Props) {
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<span className="media__subtitle--centered">
|
<span className="media__subtitle--centered">
|
||||||
{livestream &&
|
|
||||||
__('%viewer_count% currently %viewer_state%', {
|
|
||||||
viewer_count: activeViewers === undefined ? '...' : activeViewers,
|
|
||||||
viewer_state: isLive ? __('watching') : __('waiting'),
|
|
||||||
})}
|
|
||||||
{!livestream &&
|
{!livestream &&
|
||||||
activeViewers === undefined &&
|
activeViewers === undefined &&
|
||||||
(viewCount !== 1 ? __('%view_count% views', { view_count: formattedViewCount }) : __('1 view'))}
|
(viewCount !== 1 ? __('%view_count% views', { view_count: formattedViewCount }) : __('1 view'))}
|
||||||
{!SIMPLE_SITE && <HelpLink href="https://lbry.com/faq/views" />}
|
{<HelpLink href="https://lbry.com/faq/views" />}
|
||||||
</span>
|
</span>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
// @flow
|
// @flow
|
||||||
import React from 'react';
|
import React from 'react';
|
||||||
import * as ICONS from 'constants/icons';
|
import * as ICONS from 'constants/icons';
|
||||||
import { LOGO_TITLE, LOGO, LOGO_TEXT_LIGHT, LOGO_TEXT_DARK } from 'config';
|
import { LOGO, LOGO_TEXT_LIGHT, LOGO_TEXT_DARK } from 'config';
|
||||||
import Icon from 'component/common/icon';
|
import Icon from 'component/common/icon';
|
||||||
import { useIsMobile } from 'effects/use-screensize';
|
import { useIsMobile } from 'effects/use-screensize';
|
||||||
|
|
||||||
|
@ -19,9 +19,6 @@ export default function Logo(props: Props) {
|
||||||
{/* @if TARGET='app' */}
|
{/* @if TARGET='app' */}
|
||||||
<div className={'button__label'}>{'LBRY'}</div>
|
<div className={'button__label'}>{'LBRY'}</div>
|
||||||
{/* @endif */}
|
{/* @endif */}
|
||||||
{/* @if TARGET='web' */}
|
|
||||||
<div className={'button__label'}>{LOGO_TITLE}</div>
|
|
||||||
{/* @endif */}
|
|
||||||
</>
|
</>
|
||||||
);
|
);
|
||||||
|
|
||||||
|
|
|
@ -2,7 +2,6 @@
|
||||||
import type { Node } from 'react';
|
import type { Node } from 'react';
|
||||||
import React, { Fragment } from 'react';
|
import React, { Fragment } from 'react';
|
||||||
import classnames from 'classnames';
|
import classnames from 'classnames';
|
||||||
import { lazyImport } from 'util/lazyImport';
|
|
||||||
import SideNavigation from 'component/sideNavigation';
|
import SideNavigation from 'component/sideNavigation';
|
||||||
import SettingsSideNavigation from 'component/settingsSideNavigation';
|
import SettingsSideNavigation from 'component/settingsSideNavigation';
|
||||||
import Header from 'component/header';
|
import Header from 'component/header';
|
||||||
|
@ -14,8 +13,6 @@ import { useHistory } from 'react-router';
|
||||||
import { useIsMobile, useIsMediumScreen } from 'effects/use-screensize';
|
import { useIsMobile, useIsMediumScreen } from 'effects/use-screensize';
|
||||||
import { parseURI } from 'util/lbryURI';
|
import { parseURI } from 'util/lbryURI';
|
||||||
|
|
||||||
const Footer = lazyImport(() => import('web/component/footer' /* webpackChunkName: "secondary" */));
|
|
||||||
|
|
||||||
export const MAIN_CLASS = 'main';
|
export const MAIN_CLASS = 'main';
|
||||||
type Props = {
|
type Props = {
|
||||||
children: Node | Array<Node>,
|
children: Node | Array<Node>,
|
||||||
|
@ -51,7 +48,6 @@ function Page(props: Props) {
|
||||||
authPage = false,
|
authPage = false,
|
||||||
fullWidthPage = false,
|
fullWidthPage = false,
|
||||||
noHeader = false,
|
noHeader = false,
|
||||||
noFooter = false,
|
|
||||||
noSideNavigation = false,
|
noSideNavigation = false,
|
||||||
backout,
|
backout,
|
||||||
videoTheaterMode,
|
videoTheaterMode,
|
||||||
|
@ -143,13 +139,6 @@ function Page(props: Props) {
|
||||||
<StatusBar />
|
<StatusBar />
|
||||||
{/* @endif */}
|
{/* @endif */}
|
||||||
</div>
|
</div>
|
||||||
{/* @if TARGET='web' */}
|
|
||||||
{!noFooter && (
|
|
||||||
<React.Suspense fallback={null}>
|
|
||||||
<Footer />
|
|
||||||
</React.Suspense>
|
|
||||||
)}
|
|
||||||
{/* @endif */}
|
|
||||||
</Fragment>
|
</Fragment>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,5 +1,4 @@
|
||||||
// @flow
|
// @flow
|
||||||
import { SIMPLE_SITE } from 'config';
|
|
||||||
import { FF_MAX_CHARS_IN_DESCRIPTION } from 'constants/form-field';
|
import { FF_MAX_CHARS_IN_DESCRIPTION } from 'constants/form-field';
|
||||||
import React from 'react';
|
import React from 'react';
|
||||||
import { FormField } from 'component/common/form';
|
import { FormField } from 'component/common/form';
|
||||||
|
@ -23,7 +22,7 @@ function PublishDescription(props: Props) {
|
||||||
<Card
|
<Card
|
||||||
actions={
|
actions={
|
||||||
<FormField
|
<FormField
|
||||||
type={!SIMPLE_SITE && advancedEditor ? 'markdown' : 'textarea'}
|
type={'textarea'}
|
||||||
name="content_description"
|
name="content_description"
|
||||||
label={__('Description')}
|
label={__('Description')}
|
||||||
placeholder={__(
|
placeholder={__(
|
||||||
|
@ -31,10 +30,8 @@ function PublishDescription(props: Props) {
|
||||||
)}
|
)}
|
||||||
value={description}
|
value={description}
|
||||||
disabled={disabled}
|
disabled={disabled}
|
||||||
onChange={value =>
|
onChange={(value) => updatePublishForm({ description: advancedEditor ? value : value.target.value })}
|
||||||
updatePublishForm({ description: !SIMPLE_SITE && advancedEditor ? value : value.target.value })
|
quickActionLabel={advancedEditor ? __('Simple Editor') : __('Advanced Editor')}
|
||||||
}
|
|
||||||
quickActionLabel={!SIMPLE_SITE && (advancedEditor ? __('Simple Editor') : __('Advanced Editor'))}
|
|
||||||
quickActionHandler={toggleMarkdown}
|
quickActionHandler={toggleMarkdown}
|
||||||
textAreaMaxLength={FF_MAX_CHARS_IN_DESCRIPTION}
|
textAreaMaxLength={FF_MAX_CHARS_IN_DESCRIPTION}
|
||||||
/>
|
/>
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
// @flow
|
// @flow
|
||||||
import { SITE_NAME, WEB_PUBLISH_SIZE_LIMIT_GB, SIMPLE_SITE } from 'config';
|
import { SITE_NAME, WEB_PUBLISH_SIZE_LIMIT_GB } from 'config';
|
||||||
import type { Node } from 'react';
|
import type { Node } from 'react';
|
||||||
import * as ICONS from 'constants/icons';
|
import * as ICONS from 'constants/icons';
|
||||||
import React, { useState, useEffect } from 'react';
|
import React, { useState, useEffect } from 'react';
|
||||||
|
@ -522,8 +522,7 @@ function PublishFile(props: Props) {
|
||||||
currentPath={currentFile}
|
currentPath={currentFile}
|
||||||
onFileChosen={handleFileChange}
|
onFileChosen={handleFileChange}
|
||||||
// https://stackoverflow.com/questions/19107685/safari-input-type-file-accept-video-ignores-mp4-files
|
// https://stackoverflow.com/questions/19107685/safari-input-type-file-accept-video-ignores-mp4-files
|
||||||
accept={SIMPLE_SITE ? 'video/mp4,video/x-m4v,video/*,audio/*' : undefined}
|
placeholder={__('Select a file to upload')}
|
||||||
placeholder={SIMPLE_SITE ? __('Select video or audio file to upload') : __('Select a file to upload')}
|
|
||||||
/>
|
/>
|
||||||
{getUploadMessage()}
|
{getUploadMessage()}
|
||||||
</>
|
</>
|
||||||
|
|
|
@ -8,7 +8,7 @@
|
||||||
File upload is carried out in the background by that function.
|
File upload is carried out in the background by that function.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import { SITE_NAME, ENABLE_NO_SOURCE_CLAIMS, SIMPLE_SITE, CHANNEL_STAKED_LEVEL_LIVESTREAM } from 'config';
|
import { SITE_NAME, ENABLE_NO_SOURCE_CLAIMS, CHANNEL_STAKED_LEVEL_LIVESTREAM } from 'config';
|
||||||
import React, { useEffect, useState } from 'react';
|
import React, { useEffect, useState } from 'react';
|
||||||
import Lbry from 'lbry';
|
import Lbry from 'lbry';
|
||||||
import { buildURI, isURIValid, isNameValid } from 'util/lbryURI';
|
import { buildURI, isURIValid, isNameValid } from 'util/lbryURI';
|
||||||
|
@ -167,7 +167,7 @@ function PublishForm(props: Props) {
|
||||||
});
|
});
|
||||||
|
|
||||||
const MODE_TO_I18N_STR = {
|
const MODE_TO_I18N_STR = {
|
||||||
[PUBLISH_MODES.FILE]: SIMPLE_SITE ? 'Video/Audio' : 'File',
|
[PUBLISH_MODES.FILE]: 'File',
|
||||||
[PUBLISH_MODES.POST]: 'Post --[noun, markdown post tab button]--',
|
[PUBLISH_MODES.POST]: 'Post --[noun, markdown post tab button]--',
|
||||||
[PUBLISH_MODES.LIVESTREAM]: 'Livestream --[noun, livestream tab button]--',
|
[PUBLISH_MODES.LIVESTREAM]: 'Livestream --[noun, livestream tab button]--',
|
||||||
};
|
};
|
||||||
|
@ -459,17 +459,6 @@ function PublishForm(props: Props) {
|
||||||
replace({ search: newParams.toString() });
|
replace({ search: newParams.toString() });
|
||||||
}, [mode, _uploadType]);
|
}, [mode, _uploadType]);
|
||||||
|
|
||||||
// @if TARGET='web'
|
|
||||||
function createWebFile() {
|
|
||||||
if (fileText) {
|
|
||||||
const fileName = name || title;
|
|
||||||
if (fileName) {
|
|
||||||
return new File([fileText], `${fileName}.md`, { type: 'text/markdown' });
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
// @endif
|
|
||||||
|
|
||||||
// @if TARGET='app'
|
// @if TARGET='app'
|
||||||
// Save file changes locally ( desktop )
|
// Save file changes locally ( desktop )
|
||||||
function saveFileChanges() {
|
function saveFileChanges() {
|
||||||
|
@ -509,10 +498,6 @@ function PublishForm(props: Props) {
|
||||||
outputFile = await saveFileChanges();
|
outputFile = await saveFileChanges();
|
||||||
// @endif
|
// @endif
|
||||||
|
|
||||||
// @if TARGET='web'
|
|
||||||
outputFile = createWebFile();
|
|
||||||
// @endif
|
|
||||||
|
|
||||||
// New content stored locally and is not empty
|
// New content stored locally and is not empty
|
||||||
if (outputFile) {
|
if (outputFile) {
|
||||||
updatePublishForm({ filePath: outputFile });
|
updatePublishForm({ filePath: outputFile });
|
||||||
|
@ -612,7 +597,7 @@ function PublishForm(props: Props) {
|
||||||
{mode !== PUBLISH_MODES.POST && <PublishDescription disabled={formDisabled} />}
|
{mode !== PUBLISH_MODES.POST && <PublishDescription disabled={formDisabled} />}
|
||||||
<Card actions={<SelectThumbnail livestreamdData={livestreamData} />} />
|
<Card actions={<SelectThumbnail livestreamdData={livestreamData} />} />
|
||||||
<TagsSelect
|
<TagsSelect
|
||||||
suggestMature={!SIMPLE_SITE}
|
suggestMature
|
||||||
disableAutoFocus
|
disableAutoFocus
|
||||||
hideHeader
|
hideHeader
|
||||||
label={__('Selected Tags')}
|
label={__('Selected Tags')}
|
||||||
|
|
|
@ -7,7 +7,7 @@ import { PAGE_TITLE } from 'constants/pageTitles';
|
||||||
import { lazyImport } from 'util/lazyImport';
|
import { lazyImport } from 'util/lazyImport';
|
||||||
import { LINKED_COMMENT_QUERY_PARAM } from 'constants/comment';
|
import { LINKED_COMMENT_QUERY_PARAM } from 'constants/comment';
|
||||||
import { parseURI, isURIValid } from 'util/lbryURI';
|
import { parseURI, isURIValid } from 'util/lbryURI';
|
||||||
import { SITE_TITLE, WELCOME_VERSION, SIMPLE_SITE } from 'config';
|
import { SITE_TITLE, WELCOME_VERSION } from 'config';
|
||||||
import LoadingBarOneOff from 'component/loadingBarOneOff';
|
import LoadingBarOneOff from 'component/loadingBarOneOff';
|
||||||
import { GetLinksData } from 'util/buildHomepage';
|
import { GetLinksData } from 'util/buildHomepage';
|
||||||
|
|
||||||
|
@ -17,10 +17,6 @@ import HomePage from 'page/home';
|
||||||
const BackupPage = lazyImport(() => import('page/backup' /* webpackChunkName: "backup" */));
|
const BackupPage = lazyImport(() => import('page/backup' /* webpackChunkName: "backup" */));
|
||||||
// @endif
|
// @endif
|
||||||
|
|
||||||
// @if TARGET='web'
|
|
||||||
const Code2257Page = lazyImport(() => import('web/page/code2257' /* webpackChunkName: "code2257" */));
|
|
||||||
// @endif
|
|
||||||
|
|
||||||
// Chunk: "secondary"
|
// Chunk: "secondary"
|
||||||
const SignInPage = lazyImport(() => import('page/signIn' /* webpackChunkName: "secondary" */));
|
const SignInPage = lazyImport(() => import('page/signIn' /* webpackChunkName: "secondary" */));
|
||||||
const SignInWalletPasswordPage = lazyImport(() =>
|
const SignInWalletPasswordPage = lazyImport(() =>
|
||||||
|
@ -258,7 +254,6 @@ function AppRouter(props: Props) {
|
||||||
|
|
||||||
<Route path={`/`} exact component={HomePage} />
|
<Route path={`/`} exact component={HomePage} />
|
||||||
<Route path={`/$/${PAGES.DISCOVER}`} exact component={DiscoverPage} />
|
<Route path={`/$/${PAGES.DISCOVER}`} exact component={DiscoverPage} />
|
||||||
{SIMPLE_SITE && <Route path={`/$/${PAGES.WILD_WEST}`} exact component={DiscoverPage} />}
|
|
||||||
{/* $FlowFixMe */}
|
{/* $FlowFixMe */}
|
||||||
{dynamicRoutes.map((dynamicRouteProps: RowDataItem) => (
|
{dynamicRoutes.map((dynamicRouteProps: RowDataItem) => (
|
||||||
<Route
|
<Route
|
||||||
|
@ -279,9 +274,6 @@ function AppRouter(props: Props) {
|
||||||
{/* @if TARGET='app' */}
|
{/* @if TARGET='app' */}
|
||||||
<Route path={`/$/${PAGES.BACKUP}`} exact component={BackupPage} />
|
<Route path={`/$/${PAGES.BACKUP}`} exact component={BackupPage} />
|
||||||
{/* @endif */}
|
{/* @endif */}
|
||||||
{/* @if TARGET='web' */}
|
|
||||||
<Route path={`/$/${PAGES.CODE_2257}`} exact component={Code2257Page} />
|
|
||||||
{/* @endif */}
|
|
||||||
<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.TOP}`} exact component={TopPage} />
|
<Route path={`/$/${PAGES.TOP}`} exact component={TopPage} />
|
||||||
|
|
|
@ -4,7 +4,6 @@ import * as PAGES from 'constants/pages';
|
||||||
import React from 'react';
|
import React from 'react';
|
||||||
import * as SETTINGS from 'constants/settings';
|
import * as SETTINGS from 'constants/settings';
|
||||||
import { Lbryio } from 'lbryinc';
|
import { Lbryio } from 'lbryinc';
|
||||||
import { SIMPLE_SITE } from 'config';
|
|
||||||
import * as MODALS from 'constants/modal_types';
|
import * as MODALS from 'constants/modal_types';
|
||||||
import { SETTINGS_GRP } from 'constants/settings';
|
import { SETTINGS_GRP } from 'constants/settings';
|
||||||
import Button from 'component/button';
|
import Button from 'component/button';
|
||||||
|
@ -92,9 +91,6 @@ export default function SettingContent(props: Props) {
|
||||||
checked={autoplayNext}
|
checked={autoplayNext}
|
||||||
/>
|
/>
|
||||||
</SettingsRow>
|
</SettingsRow>
|
||||||
|
|
||||||
{!SIMPLE_SITE && (
|
|
||||||
<>
|
|
||||||
<SettingsRow title={__('Hide reposts')} subtitle={__(HELP.HIDE_REPOSTS)}>
|
<SettingsRow title={__('Hide reposts')} subtitle={__(HELP.HIDE_REPOSTS)}>
|
||||||
<FormField
|
<FormField
|
||||||
type="checkbox"
|
type="checkbox"
|
||||||
|
@ -108,18 +104,6 @@ export default function SettingContent(props: Props) {
|
||||||
}}
|
}}
|
||||||
/>
|
/>
|
||||||
</SettingsRow>
|
</SettingsRow>
|
||||||
|
|
||||||
{/*
|
|
||||||
<SettingsRow title={__('Show anonymous content')} subtitle={__('Anonymous content is published without a channel.')} >
|
|
||||||
<FormField
|
|
||||||
type="checkbox"
|
|
||||||
name="show_anonymous"
|
|
||||||
onChange={() => setClientSetting(SETTINGS.SHOW_ANONYMOUS, !showAnonymous)}
|
|
||||||
checked={showAnonymous}
|
|
||||||
/>
|
|
||||||
</SettingsRow>
|
|
||||||
*/}
|
|
||||||
|
|
||||||
<SettingsRow title={__('Show mature content')} subtitle={__(HELP.SHOW_MATURE)}>
|
<SettingsRow title={__('Show mature content')} subtitle={__(HELP.SHOW_MATURE)}>
|
||||||
<FormField
|
<FormField
|
||||||
type="checkbox"
|
type="checkbox"
|
||||||
|
@ -132,8 +116,6 @@ export default function SettingContent(props: Props) {
|
||||||
}
|
}
|
||||||
/>
|
/>
|
||||||
</SettingsRow>
|
</SettingsRow>
|
||||||
</>
|
|
||||||
)}
|
|
||||||
|
|
||||||
{(isAuthenticated || !IS_WEB) && (
|
{(isAuthenticated || !IS_WEB) && (
|
||||||
<>
|
<>
|
||||||
|
|
|
@ -10,11 +10,8 @@ import Icon from 'component/common/icon';
|
||||||
import NotificationBubble from 'component/notificationBubble';
|
import NotificationBubble from 'component/notificationBubble';
|
||||||
import I18nMessage from 'component/i18nMessage';
|
import I18nMessage from 'component/i18nMessage';
|
||||||
import ChannelThumbnail from 'component/channelThumbnail';
|
import ChannelThumbnail from 'component/channelThumbnail';
|
||||||
import { GetLinksData } from 'util/buildHomepage';
|
import { DOMAIN, ENABLE_UI_NOTIFICATIONS } from 'config';
|
||||||
import { SIMPLE_SITE, DOMAIN, ENABLE_UI_NOTIFICATIONS } from 'config';
|
|
||||||
// @if TARGET='app'
|
|
||||||
import { IS_MAC } from 'component/app/view';
|
import { IS_MAC } from 'component/app/view';
|
||||||
// @endif
|
|
||||||
|
|
||||||
const HOME = {
|
const HOME = {
|
||||||
title: 'Home',
|
title: 'Home',
|
||||||
|
@ -70,13 +67,10 @@ function SideNavigation(props: Props) {
|
||||||
isMediumScreen,
|
isMediumScreen,
|
||||||
isOnFilePage,
|
isOnFilePage,
|
||||||
unseenCount,
|
unseenCount,
|
||||||
homepageData,
|
|
||||||
user,
|
user,
|
||||||
followedTags,
|
followedTags,
|
||||||
} = props;
|
} = props;
|
||||||
|
|
||||||
const EXTRA_SIDEBAR_LINKS = GetLinksData(homepageData).map(({ pinnedUrls, ...theRest }) => theRest);
|
|
||||||
|
|
||||||
const FULL_LINKS: Array<SideNavLink> = [
|
const FULL_LINKS: Array<SideNavLink> = [
|
||||||
{
|
{
|
||||||
title: 'Your Tags',
|
title: 'Your Tags',
|
||||||
|
@ -203,37 +197,13 @@ function SideNavigation(props: Props) {
|
||||||
|
|
||||||
SIDE_LINKS.push(HOME);
|
SIDE_LINKS.push(HOME);
|
||||||
SIDE_LINKS.push(RECENT_FROM_FOLLOWING);
|
SIDE_LINKS.push(RECENT_FROM_FOLLOWING);
|
||||||
if (!SIMPLE_SITE) {
|
|
||||||
FULL_LINKS.push({
|
FULL_LINKS.push({
|
||||||
title: 'Lists',
|
title: 'Lists',
|
||||||
link: `/$/${PAGES.LISTS}`,
|
link: `/$/${PAGES.LISTS}`,
|
||||||
icon: ICONS.STACK,
|
icon: ICONS.STACK,
|
||||||
hideForUnauth: true,
|
hideForUnauth: true,
|
||||||
});
|
});
|
||||||
}
|
|
||||||
if (!SIMPLE_SITE) {
|
|
||||||
SIDE_LINKS.push(...FULL_LINKS);
|
SIDE_LINKS.push(...FULL_LINKS);
|
||||||
} else if (SIMPLE_SITE) {
|
|
||||||
SIDE_LINKS.push({
|
|
||||||
title: 'Lists',
|
|
||||||
link: `/$/${PAGES.LISTS}`,
|
|
||||||
icon: ICONS.STACK,
|
|
||||||
hideForUnauth: true,
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
if (SIMPLE_SITE && EXTRA_SIDEBAR_LINKS) {
|
|
||||||
// $FlowFixMe
|
|
||||||
SIDE_LINKS.push(...EXTRA_SIDEBAR_LINKS);
|
|
||||||
|
|
||||||
const WILD_WEST = {
|
|
||||||
title: 'Wild West',
|
|
||||||
link: `/$/${PAGES.WILD_WEST}`,
|
|
||||||
icon: ICONS.WILD_WEST,
|
|
||||||
};
|
|
||||||
|
|
||||||
SIDE_LINKS.push(WILD_WEST);
|
|
||||||
}
|
|
||||||
|
|
||||||
const [pulseLibrary, setPulseLibrary] = React.useState(false);
|
const [pulseLibrary, setPulseLibrary] = React.useState(false);
|
||||||
const isPersonalized = !IS_WEB || isAuthenticated;
|
const isPersonalized = !IS_WEB || isAuthenticated;
|
||||||
|
@ -304,11 +274,6 @@ function SideNavigation(props: Props) {
|
||||||
<li className="navigation-link">
|
<li className="navigation-link">
|
||||||
<Button label={__('FAQ')} href="https://odysee.com/@OdyseeHelp:b" />
|
<Button label={__('FAQ')} href="https://odysee.com/@OdyseeHelp:b" />
|
||||||
</li>
|
</li>
|
||||||
{SIMPLE_SITE && ( // GUIDELINES_URL?
|
|
||||||
<li className="navigation-link">
|
|
||||||
<Button label={__('Community Guidelines')} href="https://odysee.com/@OdyseeHelp:b/Community-Guidelines:c" />
|
|
||||||
</li>
|
|
||||||
)}
|
|
||||||
<li className="navigation-link">
|
<li className="navigation-link">
|
||||||
<Button label={__('Support --[used in footer; general help/support]--')} href="https://lbry.com/support" />
|
<Button label={__('Support --[used in footer; general help/support]--')} href="https://lbry.com/support" />
|
||||||
</li>
|
</li>
|
||||||
|
@ -384,7 +349,7 @@ function SideNavigation(props: Props) {
|
||||||
{!isAuthenticated && sidebarOpen && unAuthNudge}
|
{!isAuthenticated && sidebarOpen && unAuthNudge}
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
{SIMPLE_SITE && sidebarOpen && helpLinks}
|
{sidebarOpen && helpLinks}
|
||||||
</nav>
|
</nav>
|
||||||
)}
|
)}
|
||||||
|
|
||||||
|
@ -457,7 +422,6 @@ function SideNavigation(props: Props) {
|
||||||
</ul>
|
</ul>
|
||||||
)}
|
)}
|
||||||
{!isAuthenticated && unAuthNudge}
|
{!isAuthenticated && unAuthNudge}
|
||||||
{SIMPLE_SITE && helpLinks}
|
|
||||||
</div>
|
</div>
|
||||||
</nav>
|
</nav>
|
||||||
<div
|
<div
|
||||||
|
|
|
@ -6,7 +6,7 @@ import Nag from 'component/common/nag';
|
||||||
import { parseURI } from 'util/lbryURI';
|
import { parseURI } from 'util/lbryURI';
|
||||||
import Button from 'component/button';
|
import Button from 'component/button';
|
||||||
import Card from 'component/common/card';
|
import Card from 'component/common/card';
|
||||||
import { AUTO_FOLLOW_CHANNELS, CUSTOM_HOMEPAGE, SIMPLE_SITE, SITE_NAME } from 'config';
|
import { AUTO_FOLLOW_CHANNELS, CUSTOM_HOMEPAGE, SITE_NAME } from 'config';
|
||||||
|
|
||||||
type Props = {
|
type Props = {
|
||||||
subscribedChannels: Array<Subscription>,
|
subscribedChannels: Array<Subscription>,
|
||||||
|
@ -69,8 +69,6 @@ function UserChannelFollowIntro(props: Props) {
|
||||||
<React.Fragment>
|
<React.Fragment>
|
||||||
<div className="section__body">
|
<div className="section__body">
|
||||||
<ClaimListDiscover
|
<ClaimListDiscover
|
||||||
hideFilters={SIMPLE_SITE}
|
|
||||||
hideAdvancedFilter={SIMPLE_SITE}
|
|
||||||
meta={
|
meta={
|
||||||
<Button
|
<Button
|
||||||
button={subscribedChannels.length < 1 ? 'alt' : 'primary'}
|
button={subscribedChannels.length < 1 ? 'alt' : 'primary'}
|
||||||
|
@ -78,12 +76,11 @@ function UserChannelFollowIntro(props: Props) {
|
||||||
label={subscribedChannels.length < 1 ? __('Skip') : __('Continue')}
|
label={subscribedChannels.length < 1 ? __('Skip') : __('Continue')}
|
||||||
/>
|
/>
|
||||||
}
|
}
|
||||||
defaultOrderBy={SIMPLE_SITE ? CS.ORDER_BY_TOP : CS.ORDER_BY_TRENDING}
|
defaultOrderBy={CS.ORDER_BY_TRENDING}
|
||||||
defaultFreshness={CS.FRESH_ALL}
|
defaultFreshness={CS.FRESH_ALL}
|
||||||
claimType="channel"
|
claimType="channel"
|
||||||
claimIds={CUSTOM_HOMEPAGE && channelIds ? channelIds : undefined}
|
claimIds={CUSTOM_HOMEPAGE && channelIds ? channelIds : undefined}
|
||||||
defaultTags={followingCount > 3 ? CS.TAGS_FOLLOWED : undefined}
|
defaultTags={followingCount > 3 ? CS.TAGS_FOLLOWED : undefined}
|
||||||
maxPages={SIMPLE_SITE ? 3 : undefined}
|
|
||||||
/>
|
/>
|
||||||
{followingCount > 0 && (
|
{followingCount > 0 && (
|
||||||
<Nag
|
<Nag
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
// @flow
|
// @flow
|
||||||
import * as PAGES from 'constants/pages';
|
import * as PAGES from 'constants/pages';
|
||||||
import { DOMAIN, SIMPLE_SITE } from 'config';
|
import { DOMAIN } from 'config';
|
||||||
import React, { useState } from 'react';
|
import React, { useState } from 'react';
|
||||||
import { FormField, Form } from 'component/common/form';
|
import { FormField, Form } from 'component/common/form';
|
||||||
import Button from 'component/button';
|
import Button from 'component/button';
|
||||||
|
@ -12,7 +12,6 @@ import Card from 'component/common/card';
|
||||||
import ErrorText from 'component/common/error-text';
|
import ErrorText from 'component/common/error-text';
|
||||||
import Nag from 'component/common/nag';
|
import Nag from 'component/common/nag';
|
||||||
import classnames from 'classnames';
|
import classnames from 'classnames';
|
||||||
import LoginGraphic from 'component/loginGraphic';
|
|
||||||
|
|
||||||
type Props = {
|
type Props = {
|
||||||
errorMessage: ?string,
|
errorMessage: ?string,
|
||||||
|
@ -93,11 +92,7 @@ function UserEmailNew(props: Props) {
|
||||||
}, [emailExists]);
|
}, [emailExists]);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div
|
<div className={classnames('main__sign-up')}>
|
||||||
className={classnames('main__sign-up', {
|
|
||||||
'main__sign-up--graphic': SIMPLE_SITE,
|
|
||||||
})}
|
|
||||||
>
|
|
||||||
<Card
|
<Card
|
||||||
title={__('Join')}
|
title={__('Join')}
|
||||||
// @if TARGET='app'
|
// @if TARGET='app'
|
||||||
|
@ -187,7 +182,6 @@ function UserEmailNew(props: Props) {
|
||||||
</div>
|
</div>
|
||||||
}
|
}
|
||||||
nag={<>{errorMessage && <Nag type="error" relative message={<ErrorText>{errorMessage}</ErrorText>} />}</>}
|
nag={<>{errorMessage && <Nag type="error" relative message={<ErrorText>{errorMessage}</ErrorText>} />}</>}
|
||||||
secondPane={SIMPLE_SITE && <LoginGraphic />}
|
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
// @flow
|
// @flow
|
||||||
import { SITE_NAME, SIMPLE_SITE } from 'config';
|
import { SITE_NAME } from 'config';
|
||||||
import * as PAGES from 'constants/pages';
|
import * as PAGES from 'constants/pages';
|
||||||
import React, { useState } from 'react';
|
import React, { useState } from 'react';
|
||||||
import { FormField, Form } from 'component/common/form';
|
import { FormField, Form } from 'component/common/form';
|
||||||
|
@ -10,7 +10,6 @@ import UserEmailVerify from 'component/userEmailVerify';
|
||||||
import Card from 'component/common/card';
|
import Card from 'component/common/card';
|
||||||
import Nag from 'component/common/nag';
|
import Nag from 'component/common/nag';
|
||||||
import classnames from 'classnames';
|
import classnames from 'classnames';
|
||||||
import LoginGraphic from 'component/loginGraphic';
|
|
||||||
|
|
||||||
type Props = {
|
type Props = {
|
||||||
user: ?User,
|
user: ?User,
|
||||||
|
@ -71,11 +70,7 @@ function UserEmailReturning(props: Props) {
|
||||||
}
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div
|
<div className={classnames('main__sign-in')}>
|
||||||
className={classnames('main__sign-in', {
|
|
||||||
'main__sign-up--graphic': SIMPLE_SITE && !showEmailVerification,
|
|
||||||
})}
|
|
||||||
>
|
|
||||||
{showEmailVerification ? (
|
{showEmailVerification ? (
|
||||||
<UserEmailVerify />
|
<UserEmailVerify />
|
||||||
) : (
|
) : (
|
||||||
|
@ -142,7 +137,6 @@ function UserEmailReturning(props: Props) {
|
||||||
)}
|
)}
|
||||||
</>
|
</>
|
||||||
}
|
}
|
||||||
secondPane={SIMPLE_SITE && <LoginGraphic />}
|
|
||||||
/>
|
/>
|
||||||
)}
|
)}
|
||||||
</div>
|
</div>
|
||||||
|
|
|
@ -3,13 +3,7 @@ import * as React from 'react';
|
||||||
import Villain from 'villain-react';
|
import Villain from 'villain-react';
|
||||||
import LoadingScreen from 'component/common/loading-screen';
|
import LoadingScreen from 'component/common/loading-screen';
|
||||||
|
|
||||||
// @if TARGET='web'
|
|
||||||
import useStream from 'effects/use-stream';
|
|
||||||
// @endif
|
|
||||||
|
|
||||||
// @if TARGET='app'
|
|
||||||
import useFileStream from 'effects/use-stream-file';
|
import useFileStream from 'effects/use-stream-file';
|
||||||
// @endif
|
|
||||||
|
|
||||||
// Import default styles for Villain
|
// Import default styles for Villain
|
||||||
import 'villain-react/dist/style.css';
|
import 'villain-react/dist/style.css';
|
||||||
|
@ -33,13 +27,7 @@ const ComicBookViewer = (props: Props) => {
|
||||||
const { source, theme } = props;
|
const { source, theme } = props;
|
||||||
let finalSource;
|
let finalSource;
|
||||||
|
|
||||||
// @if TARGET='web'
|
|
||||||
finalSource = useStream(source.stream);
|
|
||||||
// @endif
|
|
||||||
|
|
||||||
// @if TARGET='app'
|
|
||||||
finalSource = useFileStream(source.file);
|
finalSource = useFileStream(source.file);
|
||||||
// @endif
|
|
||||||
|
|
||||||
// Villain options
|
// Villain options
|
||||||
const opts = {
|
const opts = {
|
||||||
|
|
|
@ -5,7 +5,6 @@ import LoadingScreen from 'component/common/loading-screen';
|
||||||
import MarkdownPreview from 'component/common/markdown-preview';
|
import MarkdownPreview from 'component/common/markdown-preview';
|
||||||
import CodeViewer from 'component/viewers/codeViewer';
|
import CodeViewer from 'component/viewers/codeViewer';
|
||||||
import * as RENDER_MODES from 'constants/file_render_modes';
|
import * as RENDER_MODES from 'constants/file_render_modes';
|
||||||
import * as https from 'https';
|
|
||||||
|
|
||||||
type Props = {
|
type Props = {
|
||||||
theme: string,
|
theme: string,
|
||||||
|
@ -35,7 +34,6 @@ class DocumentViewer extends React.PureComponent<Props, State> {
|
||||||
|
|
||||||
componentDidMount() {
|
componentDidMount() {
|
||||||
const { source } = this.props;
|
const { source } = this.props;
|
||||||
// @if TARGET='app'
|
|
||||||
if (source && source.file) {
|
if (source && source.file) {
|
||||||
const stream = source.file('utf8');
|
const stream = source.file('utf8');
|
||||||
|
|
||||||
|
@ -53,24 +51,6 @@ class DocumentViewer extends React.PureComponent<Props, State> {
|
||||||
this.setState({ error: true, loading: false });
|
this.setState({ error: true, loading: false });
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
// @endif
|
|
||||||
// @if TARGET='web'
|
|
||||||
if (source && source.stream) {
|
|
||||||
https.get(source.stream, (response) => {
|
|
||||||
if (response.statusCode === 200) {
|
|
||||||
let data = '';
|
|
||||||
response.on('data', (chunk) => {
|
|
||||||
data += chunk;
|
|
||||||
});
|
|
||||||
response.on('end', () => {
|
|
||||||
this.setState({ content: data, loading: false });
|
|
||||||
});
|
|
||||||
} else {
|
|
||||||
this.setState({ error: true, loading: false });
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
// @endif
|
|
||||||
}
|
}
|
||||||
|
|
||||||
renderDocument() {
|
renderDocument() {
|
||||||
|
|
|
@ -37,12 +37,7 @@ class HtmlViewer extends React.PureComponent<Props, State> {
|
||||||
return (
|
return (
|
||||||
<div className="file-viewer file-viewer--html file-viewer--iframe" onContextMenu={stopContextMenu}>
|
<div className="file-viewer file-viewer--html file-viewer--iframe" onContextMenu={stopContextMenu}>
|
||||||
{loading && <div className="placeholder--text-document" />}
|
{loading && <div className="placeholder--text-document" />}
|
||||||
{/* @if TARGET='app' */}
|
|
||||||
<iframe ref={this.iframe} hidden={loading} sandbox="" title={__('File preview')} src={`file://${source}`} />
|
<iframe ref={this.iframe} hidden={loading} sandbox="" title={__('File preview')} src={`file://${source}`} />
|
||||||
{/* @endif */}
|
|
||||||
{/* @if TARGET='web' */}
|
|
||||||
<iframe ref={this.iframe} hidden={loading} sandbox="" title={__('File preview')} src={source} />
|
|
||||||
{/* @endif */}
|
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,6 +1,5 @@
|
||||||
// @flow
|
// @flow
|
||||||
import React, { useEffect, useRef, useState } from 'react';
|
import React, { useEffect, useRef, useState } from 'react';
|
||||||
// import { SIMPLE_SITE } from 'config';
|
|
||||||
import Button from 'component/button';
|
import Button from 'component/button';
|
||||||
import * as ICONS from 'constants/icons';
|
import * as ICONS from 'constants/icons';
|
||||||
import * as KEYCODES from 'constants/keycodes';
|
import * as KEYCODES from 'constants/keycodes';
|
||||||
|
@ -14,10 +13,7 @@ import hlsQualitySelector from './plugins/videojs-hls-quality-selector/plugin';
|
||||||
import recsys from './plugins/videojs-recsys/plugin';
|
import recsys from './plugins/videojs-recsys/plugin';
|
||||||
import qualityLevels from 'videojs-contrib-quality-levels';
|
import qualityLevels from 'videojs-contrib-quality-levels';
|
||||||
import isUserTyping from 'util/detect-typing';
|
import isUserTyping from 'util/detect-typing';
|
||||||
// @if TARGET='web'
|
|
||||||
// Disabled for now.
|
|
||||||
// import './plugins/videojs-aniview/plugin';
|
|
||||||
// @endif
|
|
||||||
const isDev = process.env.NODE_ENV !== 'production';
|
const isDev = process.env.NODE_ENV !== 'production';
|
||||||
|
|
||||||
export type Player = {
|
export type Player = {
|
||||||
|
@ -582,19 +578,6 @@ export default React.memo<Props>(function VideoJs(props: Props) {
|
||||||
onPlayerReady(player, videoNode);
|
onPlayerReady(player, videoNode);
|
||||||
});
|
});
|
||||||
|
|
||||||
// pre-roll ads
|
|
||||||
// This must be initialized earlier than everything else
|
|
||||||
// otherwise a race condition occurs if we place this in the onReady call back
|
|
||||||
// allow if isDev because otherwise you'll never see ads when basing to master
|
|
||||||
// @if TARGET='web'
|
|
||||||
// DISABLED FOR NOW
|
|
||||||
// if ((allowPreRoll && SIMPLE_SITE) || isDev) {
|
|
||||||
// vjs.aniview();
|
|
||||||
// }
|
|
||||||
// @endif
|
|
||||||
|
|
||||||
// fixes #3498 (https://github.com/lbryio/lbry-desktop/issues/3498)
|
|
||||||
// summary: on firefox the focus would stick to the fullscreen button which caused buggy behavior with spacebar
|
|
||||||
vjs.on('fullscreenchange', () => document.activeElement && document.activeElement.blur());
|
vjs.on('fullscreenchange', () => document.activeElement && document.activeElement.blur());
|
||||||
|
|
||||||
return vjs;
|
return vjs;
|
||||||
|
|
12
ui/i18n.js
12
ui/i18n.js
|
@ -31,7 +31,7 @@ function saveMessageDesktop(message) {
|
||||||
knownMessages[message] = removeContextMetadata(message);
|
knownMessages[message] = removeContextMetadata(message);
|
||||||
knownMessages[END] = END;
|
knownMessages[END] = END;
|
||||||
|
|
||||||
fs.writeFile(messagesFilePath, JSON.stringify(knownMessages, null, 2) + '\n', 'utf-8', err => {
|
fs.writeFile(messagesFilePath, JSON.stringify(knownMessages, null, 2) + '\n', 'utf-8', (err) => {
|
||||||
if (err) {
|
if (err) {
|
||||||
throw err;
|
throw err;
|
||||||
}
|
}
|
||||||
|
@ -44,14 +44,6 @@ function saveMessageDesktop(message) {
|
||||||
I dislike the below code (and note that it ships all the way to the distributed app),
|
I dislike the below code (and note that it ships all the way to the distributed app),
|
||||||
but this seems better than silently having this limitation and future devs not knowing.
|
but this seems better than silently having this limitation and future devs not knowing.
|
||||||
*/
|
*/
|
||||||
// @if TARGET='web'
|
|
||||||
function saveMessageWeb(message) {
|
|
||||||
if (!isProduction && knownMessages === null) {
|
|
||||||
console.log('Note that i18n messages are not saved in web dev mode.'); // eslint-disable-line
|
|
||||||
knownMessages = {};
|
|
||||||
}
|
|
||||||
}
|
|
||||||
// @endif
|
|
||||||
|
|
||||||
function removeContextMetadata(message) {
|
function removeContextMetadata(message) {
|
||||||
// Example string entries with context-metadata:
|
// Example string entries with context-metadata:
|
||||||
|
@ -87,7 +79,7 @@ export function __(message, tokens) {
|
||||||
? window.localStorage.getItem('language') || 'en'
|
? window.localStorage.getItem('language') || 'en'
|
||||||
: window.navigator.language.slice(0, 2) || 'en';
|
: window.navigator.language.slice(0, 2) || 'en';
|
||||||
if (!isProduction) {
|
if (!isProduction) {
|
||||||
IS_WEB ? saveMessageWeb(message) : saveMessageDesktop(message);
|
saveMessageDesktop(message);
|
||||||
}
|
}
|
||||||
|
|
||||||
let translatedMessage = window.i18n_messages[language] ? window.i18n_messages[language][message] || message : message;
|
let translatedMessage = window.i18n_messages[language] ? window.i18n_messages[language][message] || message : message;
|
||||||
|
|
75
ui/index.jsx
75
ui/index.jsx
|
@ -1,13 +1,10 @@
|
||||||
import 'babel-polyfill';
|
import 'babel-polyfill';
|
||||||
import * as Sentry from '@sentry/browser';
|
|
||||||
import ErrorBoundary from 'component/errorBoundary';
|
import ErrorBoundary from 'component/errorBoundary';
|
||||||
import App from 'component/app';
|
import App from 'component/app';
|
||||||
import SnackBar from 'component/snackBar';
|
import SnackBar from 'component/snackBar';
|
||||||
// @if TARGET='app'
|
|
||||||
import SplashScreen from 'component/splash';
|
import SplashScreen from 'component/splash';
|
||||||
import * as ACTIONS from 'constants/action_types';
|
import * as ACTIONS from 'constants/action_types';
|
||||||
import { changeZoomFactor } from 'util/zoomWindow';
|
import { changeZoomFactor } from 'util/zoomWindow';
|
||||||
// @endif
|
|
||||||
import { ipcRenderer, remote, shell } from 'electron';
|
import { ipcRenderer, remote, shell } from 'electron';
|
||||||
import moment from 'moment';
|
import moment from 'moment';
|
||||||
import * as MODALS from 'constants/modal_types';
|
import * as MODALS from 'constants/modal_types';
|
||||||
|
@ -15,11 +12,10 @@ 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 { doDaemonReady, doAutoUpdate, doOpenModal, doHideModal, doToggle3PAnalytics } from 'redux/actions/app';
|
import { doDaemonReady, doAutoUpdate, doOpenModal, doHideModal, doToggle3PAnalytics } from 'redux/actions/app';
|
||||||
import Lbry, { apiCall } from 'lbry';
|
|
||||||
import { isURIValid } from 'util/lbryURI';
|
import { isURIValid } from 'util/lbryURI';
|
||||||
import { setSearchApi } from 'redux/actions/search';
|
import { setSearchApi } from 'redux/actions/search';
|
||||||
import { doSetLanguage, doFetchLanguage, doUpdateIsNightAsync } from 'redux/actions/settings';
|
import { doSetLanguage, doFetchLanguage, doUpdateIsNightAsync } from 'redux/actions/settings';
|
||||||
import { Lbryio, doBlackListedOutpointsSubscribe, doFilteredOutpointsSubscribe, testTheThing } from 'lbryinc';
|
import { Lbryio, doBlackListedOutpointsSubscribe, doFilteredOutpointsSubscribe } from 'lbryinc';
|
||||||
import rewards from 'rewards';
|
import rewards from 'rewards';
|
||||||
import { store, persistor, history } from 'store';
|
import { store, persistor, history } from 'store';
|
||||||
import app from './app';
|
import app from './app';
|
||||||
|
@ -29,14 +25,8 @@ import { formatLbryUrlForWeb, formatInAppUrl } 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 { doToast } from 'redux/actions/notifications';
|
import { doToast } from 'redux/actions/notifications';
|
||||||
import {
|
import { getAuthToken, setAuthToken, doAuthTokenRefresh } from 'util/saved-passwords';
|
||||||
getAuthToken,
|
import { DEFAULT_LANGUAGE, LBRY_API_URL } from 'config';
|
||||||
setAuthToken,
|
|
||||||
doDeprecatedPasswordMigrationMarch2020,
|
|
||||||
doAuthTokenRefresh,
|
|
||||||
} from 'util/saved-passwords';
|
|
||||||
import { X_LBRY_AUTH_TOKEN } from 'constants/token';
|
|
||||||
import { LBRY_WEB_API, DEFAULT_LANGUAGE, LBRY_API_URL, LBRY_WEB_PUBLISH_API } from 'config';
|
|
||||||
|
|
||||||
// Import 3rd-party styles before ours for the current way we are code-splitting.
|
// Import 3rd-party styles before ours for the current way we are code-splitting.
|
||||||
import 'scss/third-party.scss';
|
import 'scss/third-party.scss';
|
||||||
|
@ -44,68 +34,13 @@ import 'scss/third-party.scss';
|
||||||
// Import our app styles
|
// Import our app styles
|
||||||
// If a style is not necessary for the initial page load, it should be removed from `all.scss`
|
// If a style is not necessary for the initial page load, it should be removed from `all.scss`
|
||||||
// and loaded dynamically in the component that consumes it
|
// and loaded dynamically in the component that consumes it
|
||||||
// @if TARGET='app'
|
|
||||||
import 'scss/all.scss';
|
import 'scss/all.scss';
|
||||||
// @endif
|
|
||||||
// @if TARGET='web'
|
|
||||||
import 'web/theme';
|
|
||||||
// @endif
|
|
||||||
// @if TARGET='web'
|
|
||||||
// These overrides can't live in web/ because they need to use the same instance of `Lbry`
|
|
||||||
import apiPublishCallViaWeb from 'web/setup/publish';
|
|
||||||
|
|
||||||
// Sentry error logging setup
|
|
||||||
// Will only work if you have a SENTRY_AUTH_TOKEN env
|
|
||||||
// We still add code in analytics.js to send the error to sentry manually
|
|
||||||
// If it's caught by componentDidCatch in component/errorBoundary, it will not bubble up to this error reporter
|
|
||||||
if (process.env.NODE_ENV === 'production') {
|
|
||||||
Sentry.init({
|
|
||||||
dsn: 'https://1f3c88e2e4b341328a638e138a60fb73@sentry.lbry.tech/2',
|
|
||||||
whitelistUrls: [/\/public\/ui.js/],
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
testTheThing();
|
|
||||||
|
|
||||||
if (process.env.SDK_API_URL) {
|
|
||||||
console.warn('SDK_API_URL env var is deprecated. Use SDK_API_HOST instead'); // @eslint-disable-line
|
|
||||||
}
|
|
||||||
|
|
||||||
let sdkAPIHost = process.env.SDK_API_HOST || process.env.SDK_API_URL;
|
|
||||||
sdkAPIHost = LBRY_WEB_API;
|
|
||||||
|
|
||||||
export const SDK_API_PATH = `${sdkAPIHost}/api/v1`;
|
|
||||||
const proxyURL = `${SDK_API_PATH}/proxy`;
|
|
||||||
const publishURL = LBRY_WEB_PUBLISH_API; // || `${SDK_API_PATH}/proxy`;
|
|
||||||
|
|
||||||
Lbry.setDaemonConnectionString(proxyURL);
|
|
||||||
|
|
||||||
Lbry.setOverride(
|
|
||||||
'publish',
|
|
||||||
(params) =>
|
|
||||||
new Promise((resolve, reject) => {
|
|
||||||
apiPublishCallViaWeb(
|
|
||||||
apiCall,
|
|
||||||
publishURL,
|
|
||||||
Lbry.getApiRequestHeaders() && Object.keys(Lbry.getApiRequestHeaders()).includes(X_LBRY_AUTH_TOKEN)
|
|
||||||
? Lbry.getApiRequestHeaders()[X_LBRY_AUTH_TOKEN]
|
|
||||||
: '',
|
|
||||||
'publish',
|
|
||||||
params,
|
|
||||||
resolve,
|
|
||||||
reject
|
|
||||||
);
|
|
||||||
})
|
|
||||||
);
|
|
||||||
// @endif
|
|
||||||
|
|
||||||
const startTime = Date.now();
|
const startTime = Date.now();
|
||||||
analytics.startupEvent();
|
analytics.startupEvent();
|
||||||
|
|
||||||
// @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');
|
||||||
// @endif
|
|
||||||
|
|
||||||
if (LBRY_API_URL) {
|
if (LBRY_API_URL) {
|
||||||
Lbryio.setLocalApi(LBRY_API_URL);
|
Lbryio.setLocalApi(LBRY_API_URL);
|
||||||
|
@ -115,10 +50,6 @@ if (process.env.SEARCH_API_URL) {
|
||||||
setSearchApi(process.env.SEARCH_API_URL);
|
setSearchApi(process.env.SEARCH_API_URL);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Fix to make sure old users' cookies are set to the correct domain
|
|
||||||
// This can be removed after March 11th, 2021
|
|
||||||
// https://github.com/lbryio/lbry-desktop/pull/3830
|
|
||||||
doDeprecatedPasswordMigrationMarch2020();
|
|
||||||
doAuthTokenRefresh();
|
doAuthTokenRefresh();
|
||||||
|
|
||||||
// We need to override Lbryio for getting/setting the authToken
|
// We need to override Lbryio for getting/setting the authToken
|
||||||
|
|
|
@ -1,5 +1,4 @@
|
||||||
// @flow
|
// @flow
|
||||||
import { SIMPLE_SITE } from 'config';
|
|
||||||
import * as PAGES from 'constants/pages';
|
import * as PAGES from 'constants/pages';
|
||||||
import React from 'react';
|
import React from 'react';
|
||||||
import { Modal } from 'modal/modal';
|
import { Modal } from 'modal/modal';
|
||||||
|
@ -16,9 +15,8 @@ const YoutubeWelcome = (props: Props) => {
|
||||||
<Modal isOpen type="card" onAborted={doHideModal}>
|
<Modal isOpen type="card" onAborted={doHideModal}>
|
||||||
<Confetti recycle={false} style={{ position: 'fixed' }} numberOfPieces={100} />
|
<Confetti recycle={false} style={{ position: 'fixed' }} numberOfPieces={100} />
|
||||||
<Card
|
<Card
|
||||||
title={!SIMPLE_SITE ? __("You're free!") : __('Welcome to Odysee')}
|
title={__("You're free!")}
|
||||||
subtitle={
|
subtitle={
|
||||||
!SIMPLE_SITE ? (
|
|
||||||
<React.Fragment>
|
<React.Fragment>
|
||||||
<p>
|
<p>
|
||||||
{__("You've escaped the land of spying, censorship, and exploitation.")}
|
{__("You've escaped the land of spying, censorship, and exploitation.")}
|
||||||
|
@ -29,14 +27,6 @@ const YoutubeWelcome = (props: Props) => {
|
||||||
<span className="emoji"> 🌈</span>
|
<span className="emoji"> 🌈</span>
|
||||||
</p>
|
</p>
|
||||||
</React.Fragment>
|
</React.Fragment>
|
||||||
) : (
|
|
||||||
<React.Fragment>
|
|
||||||
<p>
|
|
||||||
{__('You make the party extra special!')}
|
|
||||||
<span className="emoji"> 💖</span>
|
|
||||||
</p>
|
|
||||||
</React.Fragment>
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
actions={
|
actions={
|
||||||
<div className="card__actions">
|
<div className="card__actions">
|
||||||
|
|
|
@ -14,7 +14,6 @@ import Button from 'component/button';
|
||||||
import Nag from 'component/common/nag';
|
import Nag from 'component/common/nag';
|
||||||
import I18nMessage from 'component/i18nMessage';
|
import I18nMessage from 'component/i18nMessage';
|
||||||
import LbcSymbol from 'component/common/lbc-symbol';
|
import LbcSymbol from 'component/common/lbc-symbol';
|
||||||
import { SIMPLE_SITE } from 'config';
|
|
||||||
import classnames from 'classnames';
|
import classnames from 'classnames';
|
||||||
import WalletSwap from 'component/walletSwap';
|
import WalletSwap from 'component/walletSwap';
|
||||||
|
|
||||||
|
@ -76,9 +75,7 @@ export default function BuyPage(props: Props) {
|
||||||
|
|
||||||
React.useEffect(() => {
|
React.useEffect(() => {
|
||||||
if (MOONPAY_KEY && !url && receiveAddress) {
|
if (MOONPAY_KEY && !url && receiveAddress) {
|
||||||
let url = SIMPLE_SITE
|
let url = `https://buy.moonpay.io?apiKey=pk_live_xNFffrN5NWKy6fu0ggbV8VQIwRieRzy&colorCode=%23257761¤cyCode=lbc&showWalletAddressForm=true&walletAddress=${receiveAddress}`;
|
||||||
? `https://buy.moonpay.io?apiKey=pk_live_xNFffrN5NWKy6fu0ggbV8VQIwRieRzy&colorCode=%23fa6165¤cyCode=lbc&showWalletAddressForm=true&walletAddress=${receiveAddress}`
|
|
||||||
: `https://buy.moonpay.io?apiKey=pk_live_xNFffrN5NWKy6fu0ggbV8VQIwRieRzy&colorCode=%23257761¤cyCode=lbc&showWalletAddressForm=true&walletAddress=${receiveAddress}`;
|
|
||||||
|
|
||||||
if (email) {
|
if (email) {
|
||||||
url += `&email=${encodeURIComponent(email)}`;
|
url += `&email=${encodeURIComponent(email)}`;
|
||||||
|
|
|
@ -1,7 +1,5 @@
|
||||||
import { connect } from 'react-redux';
|
import { connect } from 'react-redux';
|
||||||
import * as SETTINGS from 'constants/settings';
|
import * as SETTINGS from 'constants/settings';
|
||||||
import { doFetchActiveLivestreams } from 'redux/actions/livestream';
|
|
||||||
import { selectActiveLivestreams } from 'redux/selectors/livestream';
|
|
||||||
import { selectSubscriptions } from 'redux/selectors/subscriptions';
|
import { selectSubscriptions } from 'redux/selectors/subscriptions';
|
||||||
import { makeSelectClientSetting } from 'redux/selectors/settings';
|
import { makeSelectClientSetting } from 'redux/selectors/settings';
|
||||||
|
|
||||||
|
@ -10,9 +8,6 @@ import ChannelsFollowingPage from './view';
|
||||||
const select = (state) => ({
|
const select = (state) => ({
|
||||||
subscribedChannels: selectSubscriptions(state),
|
subscribedChannels: selectSubscriptions(state),
|
||||||
tileLayout: makeSelectClientSetting(SETTINGS.TILE_LAYOUT)(state),
|
tileLayout: makeSelectClientSetting(SETTINGS.TILE_LAYOUT)(state),
|
||||||
activeLivestreams: selectActiveLivestreams(state),
|
|
||||||
});
|
});
|
||||||
|
|
||||||
export default connect(select, {
|
export default connect(select)(ChannelsFollowingPage);
|
||||||
doFetchActiveLivestreams,
|
|
||||||
})(ChannelsFollowingPage);
|
|
||||||
|
|
|
@ -2,7 +2,7 @@
|
||||||
import * as PAGES from 'constants/pages';
|
import * as PAGES from 'constants/pages';
|
||||||
import * as ICONS from 'constants/icons';
|
import * as ICONS from 'constants/icons';
|
||||||
import * as CS from 'constants/claim_search';
|
import * as CS from 'constants/claim_search';
|
||||||
import { SIMPLE_SITE, ENABLE_NO_SOURCE_CLAIMS } from 'config';
|
import { ENABLE_NO_SOURCE_CLAIMS } from 'config';
|
||||||
import React from 'react';
|
import React from 'react';
|
||||||
import ChannelsFollowingDiscoverPage from 'page/channelsFollowingDiscover';
|
import ChannelsFollowingDiscoverPage from 'page/channelsFollowingDiscover';
|
||||||
import ClaimListDiscover from 'component/claimListDiscover';
|
import ClaimListDiscover from 'component/claimListDiscover';
|
||||||
|
@ -10,33 +10,23 @@ import Page from 'component/page';
|
||||||
import Button from 'component/button';
|
import Button from 'component/button';
|
||||||
import Icon from 'component/common/icon';
|
import Icon from 'component/common/icon';
|
||||||
import { splitBySeparator } from 'util/lbryURI';
|
import { splitBySeparator } from 'util/lbryURI';
|
||||||
import { getLivestreamUris } from 'util/livestream';
|
|
||||||
|
|
||||||
type Props = {
|
type Props = {
|
||||||
subscribedChannels: Array<Subscription>,
|
subscribedChannels: Array<Subscription>,
|
||||||
tileLayout: boolean,
|
tileLayout: boolean,
|
||||||
activeLivestreams: ?LivestreamInfo,
|
|
||||||
doFetchActiveLivestreams: () => void,
|
|
||||||
};
|
};
|
||||||
|
|
||||||
function ChannelsFollowingPage(props: Props) {
|
function ChannelsFollowingPage(props: Props) {
|
||||||
const { subscribedChannels, tileLayout, activeLivestreams, doFetchActiveLivestreams } = props;
|
const { subscribedChannels, tileLayout } = props;
|
||||||
|
|
||||||
const hasSubsribedChannels = subscribedChannels.length > 0;
|
const hasSubsribedChannels = subscribedChannels.length > 0;
|
||||||
const channelIds = subscribedChannels.map((sub) => splitBySeparator(sub.uri)[1]);
|
const channelIds = subscribedChannels.map((sub) => splitBySeparator(sub.uri)[1]);
|
||||||
|
|
||||||
React.useEffect(() => {
|
|
||||||
doFetchActiveLivestreams();
|
|
||||||
}, []);
|
|
||||||
|
|
||||||
return !hasSubsribedChannels ? (
|
return !hasSubsribedChannels ? (
|
||||||
<ChannelsFollowingDiscoverPage />
|
<ChannelsFollowingDiscoverPage />
|
||||||
) : (
|
) : (
|
||||||
<Page noFooter fullWidthPage={tileLayout}>
|
<Page noFooter fullWidthPage={tileLayout}>
|
||||||
<ClaimListDiscover
|
<ClaimListDiscover
|
||||||
prefixUris={getLivestreamUris(activeLivestreams, channelIds)}
|
|
||||||
hideAdvancedFilter={SIMPLE_SITE}
|
|
||||||
streamType={SIMPLE_SITE ? CS.CONTENT_ALL : undefined}
|
|
||||||
tileLayout={tileLayout}
|
tileLayout={tileLayout}
|
||||||
headerLabel={
|
headerLabel={
|
||||||
<span>
|
<span>
|
||||||
|
|
|
@ -8,7 +8,7 @@ import ClaimTilesDiscover from 'component/claimTilesDiscover';
|
||||||
import ClaimListDiscover from 'component/claimListDiscover';
|
import ClaimListDiscover from 'component/claimListDiscover';
|
||||||
import * as CS from 'constants/claim_search';
|
import * as CS from 'constants/claim_search';
|
||||||
import { toCapitalCase } from 'util/string';
|
import { toCapitalCase } from 'util/string';
|
||||||
import { CUSTOM_HOMEPAGE, SIMPLE_SITE } from 'config';
|
import { CUSTOM_HOMEPAGE } from 'config';
|
||||||
|
|
||||||
const MORE_CHANNELS_ANCHOR = 'MoreChannels';
|
const MORE_CHANNELS_ANCHOR = 'MoreChannels';
|
||||||
|
|
||||||
|
@ -99,8 +99,7 @@ function ChannelsFollowingDiscover(props: Props) {
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Page>
|
<Page>
|
||||||
{!SIMPLE_SITE &&
|
{rowDataWithGenericOptions.map(({ title, link, help, options = {} }) => (
|
||||||
rowDataWithGenericOptions.map(({ title, link, help, options = {} }) => (
|
|
||||||
<div key={title} className="claim-grid__wrapper">
|
<div key={title} className="claim-grid__wrapper">
|
||||||
<h1 className="section__actions">
|
<h1 className="section__actions">
|
||||||
{link ? (
|
{link ? (
|
||||||
|
@ -109,7 +108,7 @@ function ChannelsFollowingDiscover(props: Props) {
|
||||||
button="link"
|
button="link"
|
||||||
navigate={link}
|
navigate={link}
|
||||||
iconRight={ICONS.ARROW_RIGHT}
|
iconRight={ICONS.ARROW_RIGHT}
|
||||||
label={__(title)}
|
label={__(title) /* i18n this? */}
|
||||||
/>
|
/>
|
||||||
) : (
|
) : (
|
||||||
<span className="claim-grid__title">{__(title)}</span>
|
<span className="claim-grid__title">{__(title)}</span>
|
||||||
|
@ -120,20 +119,17 @@ function ChannelsFollowingDiscover(props: Props) {
|
||||||
<ClaimTilesDiscover {...options} />
|
<ClaimTilesDiscover {...options} />
|
||||||
</div>
|
</div>
|
||||||
))}
|
))}
|
||||||
{!SIMPLE_SITE && (
|
{
|
||||||
<h1 id={MORE_CHANNELS_ANCHOR} className="claim-grid__title">
|
<h1 id={MORE_CHANNELS_ANCHOR} className="claim-grid__title">
|
||||||
{__('More Channels')}
|
{__('More Channels')}
|
||||||
</h1>
|
</h1>
|
||||||
)}
|
}
|
||||||
<ClaimListDiscover
|
<ClaimListDiscover
|
||||||
defaultOrderBy={CS.ORDER_BY_TRENDING}
|
defaultOrderBy={CS.ORDER_BY_TRENDING}
|
||||||
defaultFreshness={CS.FRESH_ALL}
|
defaultFreshness={CS.FRESH_ALL}
|
||||||
claimType={CS.CLAIM_CHANNEL}
|
claimType={CS.CLAIM_CHANNEL}
|
||||||
claimIds={CUSTOM_HOMEPAGE && channelIds ? channelIds : undefined}
|
claimIds={CUSTOM_HOMEPAGE && channelIds ? channelIds : undefined}
|
||||||
scrollAnchor={MORE_CHANNELS_ANCHOR}
|
scrollAnchor={MORE_CHANNELS_ANCHOR}
|
||||||
maxPages={SIMPLE_SITE ? 3 : undefined}
|
|
||||||
hideFilters={SIMPLE_SITE}
|
|
||||||
header={SIMPLE_SITE ? <h1 className="section__title">{__('Moon cheese is an acquired taste')}</h1> : undefined}
|
|
||||||
/>
|
/>
|
||||||
</Page>
|
</Page>
|
||||||
);
|
);
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
// @flow
|
// @flow
|
||||||
import { SHOW_ADS, DOMAIN, SIMPLE_SITE, ENABLE_NO_SOURCE_CLAIMS } from 'config';
|
import { DOMAIN, ENABLE_NO_SOURCE_CLAIMS } from 'config';
|
||||||
import * as ICONS from 'constants/icons';
|
import * as ICONS from 'constants/icons';
|
||||||
import * as PAGES from 'constants/pages';
|
import * as PAGES from 'constants/pages';
|
||||||
import * as CS from 'constants/claim_search';
|
import * as CS from 'constants/claim_search';
|
||||||
|
@ -8,17 +8,14 @@ import Page from 'component/page';
|
||||||
import ClaimListDiscover from 'component/claimListDiscover';
|
import ClaimListDiscover from 'component/claimListDiscover';
|
||||||
import Button from 'component/button';
|
import Button from 'component/button';
|
||||||
import useHover from 'effects/use-hover';
|
import useHover from 'effects/use-hover';
|
||||||
import { useIsMobile, useIsLargeScreen } from 'effects/use-screensize';
|
import { useIsMobile } from 'effects/use-screensize';
|
||||||
import analytics from 'analytics';
|
import analytics from 'analytics';
|
||||||
import HiddenNsfw from 'component/common/hidden-nsfw';
|
import HiddenNsfw from 'component/common/hidden-nsfw';
|
||||||
import Icon from 'component/common/icon';
|
import Icon from 'component/common/icon';
|
||||||
import Ads from 'web/component/ads';
|
|
||||||
import LbcSymbol from 'component/common/lbc-symbol';
|
import LbcSymbol from 'component/common/lbc-symbol';
|
||||||
import I18nMessage from 'component/i18nMessage';
|
import I18nMessage from 'component/i18nMessage';
|
||||||
import moment from 'moment';
|
|
||||||
import { getLivestreamUris } from 'util/livestream';
|
|
||||||
|
|
||||||
const DEFAULT_LIVESTREAM_TILE_LIMIT = 8;
|
const LIMIT_CLAIMS_PER_CHANNEL = 3;
|
||||||
|
|
||||||
type Props = {
|
type Props = {
|
||||||
location: { search: string },
|
location: { search: string },
|
||||||
|
@ -30,8 +27,6 @@ type Props = {
|
||||||
isAuthenticated: boolean,
|
isAuthenticated: boolean,
|
||||||
dynamicRouteProps: RowDataItem,
|
dynamicRouteProps: RowDataItem,
|
||||||
tileLayout: boolean,
|
tileLayout: boolean,
|
||||||
activeLivestreams: ?LivestreamInfo,
|
|
||||||
doFetchActiveLivestreams: (orderBy?: Array<string>, pageSize?: number, forceFetch?: boolean) => void,
|
|
||||||
};
|
};
|
||||||
|
|
||||||
function DiscoverPage(props: Props) {
|
function DiscoverPage(props: Props) {
|
||||||
|
@ -42,16 +37,12 @@ function DiscoverPage(props: Props) {
|
||||||
repostedUri,
|
repostedUri,
|
||||||
doToggleTagFollowDesktop,
|
doToggleTagFollowDesktop,
|
||||||
doResolveUri,
|
doResolveUri,
|
||||||
isAuthenticated,
|
|
||||||
tileLayout,
|
tileLayout,
|
||||||
activeLivestreams,
|
|
||||||
doFetchActiveLivestreams,
|
|
||||||
dynamicRouteProps,
|
dynamicRouteProps,
|
||||||
} = props;
|
} = props;
|
||||||
const buttonRef = useRef();
|
const buttonRef = useRef();
|
||||||
const isHovering = useHover(buttonRef);
|
const isHovering = useHover(buttonRef);
|
||||||
const isMobile = useIsMobile();
|
const isMobile = useIsMobile();
|
||||||
const isLargeScreen = useIsLargeScreen();
|
|
||||||
|
|
||||||
const urlParams = new URLSearchParams(search);
|
const urlParams = new URLSearchParams(search);
|
||||||
const claimType = urlParams.get('claim_type');
|
const claimType = urlParams.get('claim_type');
|
||||||
|
@ -59,8 +50,8 @@ function DiscoverPage(props: Props) {
|
||||||
const tags = tagsQuery ? tagsQuery.split(',') : null;
|
const tags = tagsQuery ? tagsQuery.split(',') : null;
|
||||||
const repostedClaimIsResolved = repostedUri && repostedClaim;
|
const repostedClaimIsResolved = repostedUri && repostedClaim;
|
||||||
|
|
||||||
const discoverIcon = SIMPLE_SITE ? ICONS.WILD_WEST : ICONS.DISCOVER;
|
const discoverIcon = ICONS.DISCOVER;
|
||||||
const discoverLabel = SIMPLE_SITE ? __('Wild West') : __('All Content');
|
const discoverLabel = __('All Content');
|
||||||
// Eventually allow more than one tag on this page
|
// Eventually allow more than one tag on this page
|
||||||
// Restricting to one to make follow/unfollow simpler
|
// Restricting to one to make follow/unfollow simpler
|
||||||
const tag = (tags && tags[0]) || null;
|
const tag = (tags && tags[0]) || null;
|
||||||
|
@ -73,12 +64,6 @@ function DiscoverPage(props: Props) {
|
||||||
label = __('Unfollow');
|
label = __('Unfollow');
|
||||||
}
|
}
|
||||||
|
|
||||||
const initialLivestreamTileLimit = getPageSize(DEFAULT_LIVESTREAM_TILE_LIMIT);
|
|
||||||
|
|
||||||
const [showViewMoreLivestreams, setShowViewMoreLivestreams] = React.useState(!dynamicRouteProps);
|
|
||||||
const livestreamUris = getLivestreamUris(activeLivestreams, channelIds);
|
|
||||||
const useDualList = showViewMoreLivestreams && livestreamUris.length > initialLivestreamTileLimit;
|
|
||||||
|
|
||||||
function getElemMeta() {
|
function getElemMeta() {
|
||||||
return !dynamicRouteProps ? (
|
return !dynamicRouteProps ? (
|
||||||
<a
|
<a
|
||||||
|
@ -109,10 +94,6 @@ function DiscoverPage(props: Props) {
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
function getPageSize(originalSize) {
|
|
||||||
return isLargeScreen ? originalSize * (3 / 2) : originalSize;
|
|
||||||
}
|
|
||||||
|
|
||||||
React.useEffect(() => {
|
React.useEffect(() => {
|
||||||
if (repostedUri && !repostedClaimIsResolved) {
|
if (repostedUri && !repostedClaimIsResolved) {
|
||||||
doResolveUri(repostedUri);
|
doResolveUri(repostedUri);
|
||||||
|
@ -154,78 +135,24 @@ function DiscoverPage(props: Props) {
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
React.useEffect(() => {
|
// GET ELEM DATA??
|
||||||
if (showViewMoreLivestreams) {
|
|
||||||
doFetchActiveLivestreams(CS.ORDER_BY_TRENDING_VALUE);
|
|
||||||
} else {
|
|
||||||
doFetchActiveLivestreams();
|
|
||||||
}
|
|
||||||
}, []);
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Page noFooter fullWidthPage={tileLayout}>
|
<Page noFooter fullWidthPage={tileLayout}>
|
||||||
{useDualList && (
|
|
||||||
<>
|
|
||||||
<ClaimListDiscover
|
<ClaimListDiscover
|
||||||
uris={livestreamUris.slice(0, initialLivestreamTileLimit)}
|
|
||||||
headerLabel={headerLabel}
|
|
||||||
header={repostedUri ? <span /> : undefined}
|
|
||||||
tileLayout={repostedUri ? false : tileLayout}
|
tileLayout={repostedUri ? false : tileLayout}
|
||||||
hideAdvancedFilter
|
|
||||||
hideFilters
|
|
||||||
infiniteScroll={false}
|
|
||||||
showNoSourceClaims={ENABLE_NO_SOURCE_CLAIMS}
|
|
||||||
meta={getElemMeta()}
|
|
||||||
/>
|
|
||||||
<div className="livestream-list--view-more">
|
|
||||||
<Button
|
|
||||||
label={__('Show more livestreams')}
|
|
||||||
button="link"
|
|
||||||
iconRight={ICONS.ARROW_RIGHT}
|
|
||||||
className="claim-grid__title--secondary"
|
|
||||||
onClick={() => {
|
|
||||||
doFetchActiveLivestreams();
|
|
||||||
setShowViewMoreLivestreams(false);
|
|
||||||
}}
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
</>
|
|
||||||
)}
|
|
||||||
|
|
||||||
<ClaimListDiscover
|
|
||||||
prefixUris={useDualList ? undefined : livestreamUris}
|
|
||||||
hideAdvancedFilter={SIMPLE_SITE}
|
|
||||||
hideFilters={SIMPLE_SITE ? !dynamicRouteProps : undefined}
|
|
||||||
header={useDualList ? <span /> : repostedUri ? <span /> : undefined}
|
|
||||||
tileLayout={repostedUri ? false : tileLayout}
|
|
||||||
defaultOrderBy={SIMPLE_SITE ? (dynamicRouteProps ? undefined : CS.ORDER_BY_TRENDING) : undefined}
|
|
||||||
claimType={claimType ? [claimType] : undefined}
|
claimType={claimType ? [claimType] : undefined}
|
||||||
headerLabel={!useDualList && headerLabel}
|
headerLabel={headerLabel}
|
||||||
tags={tags}
|
tags={tags}
|
||||||
hiddenNsfwMessage={<HiddenNsfw type="page" />}
|
hiddenNsfwMessage={<HiddenNsfw type="page" />}
|
||||||
repostedClaimId={repostedClaim ? repostedClaim.claim_id : null}
|
repostedClaimId={repostedClaim ? repostedClaim.claim_id : null}
|
||||||
injectedItem={
|
|
||||||
SHOW_ADS && IS_WEB ? (SIMPLE_SITE ? false : !isAuthenticated && <Ads small type={'video'} />) : false
|
|
||||||
}
|
|
||||||
// Assume wild west page if no dynamicRouteProps
|
// Assume wild west page if no dynamicRouteProps
|
||||||
// Not a very good solution, but just doing it for now
|
// Not a very good solution, but just doing it for now
|
||||||
// until we are sure this page will stay around
|
// until we are sure this page will stay around
|
||||||
// TODO: find a better way to determine discover / wild west vs other modes release times
|
// TODO: find a better way to determine discover / wild west vs other modes release times
|
||||||
// for now including && !tags so that
|
// for now including && !tags so that
|
||||||
releaseTime={
|
|
||||||
SIMPLE_SITE
|
|
||||||
? !dynamicRouteProps && !tags && `>${Math.floor(moment().subtract(1, 'day').startOf('week').unix())}`
|
|
||||||
: undefined
|
|
||||||
}
|
|
||||||
feeAmount={SIMPLE_SITE ? !dynamicRouteProps && CS.FEE_AMOUNT_ANY : undefined}
|
|
||||||
channelIds={channelIds}
|
channelIds={channelIds}
|
||||||
limitClaimsPerChannel={
|
limitClaimsPerChannel={LIMIT_CLAIMS_PER_CHANNEL}
|
||||||
SIMPLE_SITE
|
meta={getElemMeta()}
|
||||||
? (dynamicRouteProps && dynamicRouteProps.options && dynamicRouteProps.options.limitClaimsPerChannel) ||
|
|
||||||
undefined
|
|
||||||
: 3
|
|
||||||
}
|
|
||||||
meta={!useDualList && getElemMeta()}
|
|
||||||
hasSource
|
hasSource
|
||||||
showNoSourceClaims={ENABLE_NO_SOURCE_CLAIMS}
|
showNoSourceClaims={ENABLE_NO_SOURCE_CLAIMS}
|
||||||
/>
|
/>
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
// @flow
|
// @flow
|
||||||
import { SITE_NAME, SIMPLE_SITE, SITE_HELP_EMAIL } from 'config';
|
import { SITE_HELP_EMAIL } from 'config';
|
||||||
import * as ICONS from 'constants/icons';
|
import * as ICONS from 'constants/icons';
|
||||||
import * as PAGES from 'constants/pages';
|
import * as PAGES from 'constants/pages';
|
||||||
import * as React from 'react';
|
import * as React from 'react';
|
||||||
|
@ -129,22 +129,11 @@ class HelpPage extends React.PureComponent<Props, State> {
|
||||||
return (
|
return (
|
||||||
<Page className="card-stack">
|
<Page className="card-stack">
|
||||||
<Card
|
<Card
|
||||||
title={SIMPLE_SITE ? __('Visit the %SITE_NAME% Help Hub', { SITE_NAME }) : __('Read the FAQ')}
|
title={__('Read the FAQ')}
|
||||||
subtitle={
|
subtitle={__('Our FAQ answers many common questions.')}
|
||||||
SIMPLE_SITE
|
|
||||||
? __('Our support posts answer many common questions.')
|
|
||||||
: __('Our FAQ answers many common questions.')
|
|
||||||
}
|
|
||||||
actions={
|
actions={
|
||||||
<div className="section__actions">
|
<div className="section__actions">
|
||||||
{SIMPLE_SITE ? (
|
{
|
||||||
<Button
|
|
||||||
href="https://odysee.com/@OdyseeHelp:b"
|
|
||||||
label={__('View %SITE_NAME% Help Hub', { SITE_NAME })}
|
|
||||||
icon={ICONS.HELP}
|
|
||||||
button="secondary"
|
|
||||||
/>
|
|
||||||
) : (
|
|
||||||
<>
|
<>
|
||||||
<Button
|
<Button
|
||||||
href="https://lbry.com/faq/lbry-basics"
|
href="https://lbry.com/faq/lbry-basics"
|
||||||
|
@ -159,7 +148,7 @@ class HelpPage extends React.PureComponent<Props, State> {
|
||||||
button="secondary"
|
button="secondary"
|
||||||
/>
|
/>
|
||||||
</>
|
</>
|
||||||
)}
|
}
|
||||||
</div>
|
</div>
|
||||||
}
|
}
|
||||||
/>
|
/>
|
||||||
|
@ -226,7 +215,6 @@ class HelpPage extends React.PureComponent<Props, State> {
|
||||||
|
|
||||||
<WalletBackup />
|
<WalletBackup />
|
||||||
{/* @endif */}
|
{/* @endif */}
|
||||||
{!SIMPLE_SITE && (
|
|
||||||
<>
|
<>
|
||||||
<Card
|
<Card
|
||||||
title={__('About --[About section in Help Page]--')}
|
title={__('About --[About section in Help Page]--')}
|
||||||
|
@ -312,7 +300,6 @@ class HelpPage extends React.PureComponent<Props, State> {
|
||||||
}
|
}
|
||||||
/>
|
/>
|
||||||
</>
|
</>
|
||||||
)}
|
|
||||||
</Page>
|
</Page>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,6 +1,4 @@
|
||||||
import { connect } from 'react-redux';
|
import { connect } from 'react-redux';
|
||||||
import { doFetchActiveLivestreams } from 'redux/actions/livestream';
|
|
||||||
import { selectActiveLivestreams } from 'redux/selectors/livestream';
|
|
||||||
import { selectFollowedTags } from 'redux/selectors/tags';
|
import { selectFollowedTags } from 'redux/selectors/tags';
|
||||||
import { selectUserVerifiedEmail } from 'redux/selectors/user';
|
import { selectUserVerifiedEmail } from 'redux/selectors/user';
|
||||||
import { selectSubscriptions } from 'redux/selectors/subscriptions';
|
import { selectSubscriptions } from 'redux/selectors/subscriptions';
|
||||||
|
@ -14,11 +12,6 @@ const select = (state) => ({
|
||||||
authenticated: selectUserVerifiedEmail(state),
|
authenticated: selectUserVerifiedEmail(state),
|
||||||
showNsfw: selectShowMatureContent(state),
|
showNsfw: selectShowMatureContent(state),
|
||||||
homepageData: selectHomepageData(state),
|
homepageData: selectHomepageData(state),
|
||||||
activeLivestreams: selectActiveLivestreams(state),
|
|
||||||
});
|
});
|
||||||
|
|
||||||
const perform = (dispatch) => ({
|
export default connect(select)(DiscoverPage);
|
||||||
doFetchActiveLivestreams: () => dispatch(doFetchActiveLivestreams()),
|
|
||||||
});
|
|
||||||
|
|
||||||
export default connect(select, perform)(DiscoverPage);
|
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
// @flow
|
// @flow
|
||||||
import * as ICONS from 'constants/icons';
|
import * as ICONS from 'constants/icons';
|
||||||
import * as PAGES from 'constants/pages';
|
import * as PAGES from 'constants/pages';
|
||||||
import { SITE_NAME, SIMPLE_SITE, ENABLE_NO_SOURCE_CLAIMS } from 'config';
|
import { SITE_NAME, ENABLE_NO_SOURCE_CLAIMS } from 'config';
|
||||||
import React from 'react';
|
import React from 'react';
|
||||||
import Page from 'component/page';
|
import Page from 'component/page';
|
||||||
import Button from 'component/button';
|
import Button from 'component/button';
|
||||||
|
@ -10,12 +10,6 @@ import ClaimPreviewTile from 'component/claimPreviewTile';
|
||||||
import Icon from 'component/common/icon';
|
import Icon from 'component/common/icon';
|
||||||
import WaitUntilOnPage from 'component/common/wait-until-on-page';
|
import WaitUntilOnPage from 'component/common/wait-until-on-page';
|
||||||
import { GetLinksData } from 'util/buildHomepage';
|
import { GetLinksData } from 'util/buildHomepage';
|
||||||
import { getLivestreamUris } from 'util/livestream';
|
|
||||||
|
|
||||||
// @if TARGET='web'
|
|
||||||
import Pixel from 'web/component/pixel';
|
|
||||||
import Meme from 'web/component/meme';
|
|
||||||
// @endif
|
|
||||||
|
|
||||||
type Props = {
|
type Props = {
|
||||||
authenticated: boolean,
|
authenticated: boolean,
|
||||||
|
@ -23,20 +17,10 @@ type Props = {
|
||||||
subscribedChannels: Array<Subscription>,
|
subscribedChannels: Array<Subscription>,
|
||||||
showNsfw: boolean,
|
showNsfw: boolean,
|
||||||
homepageData: any,
|
homepageData: any,
|
||||||
activeLivestreams: any,
|
|
||||||
doFetchActiveLivestreams: () => void,
|
|
||||||
};
|
};
|
||||||
|
|
||||||
function HomePage(props: Props) {
|
function HomePage(props: Props) {
|
||||||
const {
|
const { followedTags, subscribedChannels, authenticated, showNsfw, homepageData } = props;
|
||||||
followedTags,
|
|
||||||
subscribedChannels,
|
|
||||||
authenticated,
|
|
||||||
showNsfw,
|
|
||||||
homepageData,
|
|
||||||
activeLivestreams,
|
|
||||||
doFetchActiveLivestreams,
|
|
||||||
} = props;
|
|
||||||
const showPersonalizedChannels = (authenticated || !IS_WEB) && subscribedChannels && subscribedChannels.length > 0;
|
const showPersonalizedChannels = (authenticated || !IS_WEB) && subscribedChannels && subscribedChannels.length > 0;
|
||||||
const showPersonalizedTags = (authenticated || !IS_WEB) && followedTags && followedTags.length > 0;
|
const showPersonalizedTags = (authenticated || !IS_WEB) && followedTags && followedTags.length > 0;
|
||||||
const showIndividualTags = showPersonalizedTags && followedTags.length < 5;
|
const showIndividualTags = showPersonalizedTags && followedTags.length < 5;
|
||||||
|
@ -63,13 +47,7 @@ function HomePage(props: Props) {
|
||||||
);
|
);
|
||||||
|
|
||||||
const claimTiles = (
|
const claimTiles = (
|
||||||
<ClaimTilesDiscover
|
<ClaimTilesDiscover {...options} showNoSourceClaims={ENABLE_NO_SOURCE_CLAIMS} hasSource pinUrls={pinUrls} />
|
||||||
{...options}
|
|
||||||
showNoSourceClaims={ENABLE_NO_SOURCE_CLAIMS}
|
|
||||||
hasSource
|
|
||||||
prefixUris={getLivestreamUris(activeLivestreams, options.channelIds)}
|
|
||||||
pinUrls={pinUrls}
|
|
||||||
/>
|
|
||||||
);
|
);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
|
@ -78,7 +56,7 @@ function HomePage(props: Props) {
|
||||||
<h1 className="claim-grid__header">
|
<h1 className="claim-grid__header">
|
||||||
<Button navigate={route || link} button="link">
|
<Button navigate={route || link} button="link">
|
||||||
{icon && <Icon className="claim-grid__header-icon" sectionIcon icon={icon} size={20} />}
|
{icon && <Icon className="claim-grid__header-icon" sectionIcon icon={icon} size={20} />}
|
||||||
<span className="claim-grid__title">{__(title)}</span>
|
<span className="claim-grid__title">{title}</span>
|
||||||
{help}
|
{help}
|
||||||
</Button>
|
</Button>
|
||||||
</h1>
|
</h1>
|
||||||
|
@ -104,13 +82,9 @@ function HomePage(props: Props) {
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
React.useEffect(() => {
|
|
||||||
doFetchActiveLivestreams();
|
|
||||||
}, []);
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Page fullWidthPage>
|
<Page fullWidthPage>
|
||||||
{!SIMPLE_SITE && (authenticated || !IS_WEB) && !subscribedChannels.length && (
|
{(authenticated || !IS_WEB) && !subscribedChannels.length && (
|
||||||
<div className="notice-message">
|
<div className="notice-message">
|
||||||
<h1 className="section__title">
|
<h1 className="section__title">
|
||||||
{__("%SITE_NAME% is more fun if you're following channels", { SITE_NAME })}
|
{__("%SITE_NAME% is more fun if you're following channels", { SITE_NAME })}
|
||||||
|
@ -124,16 +98,10 @@ function HomePage(props: Props) {
|
||||||
</p>
|
</p>
|
||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
{/* @if TARGET='web' */}
|
|
||||||
{SIMPLE_SITE && <Meme />}
|
|
||||||
{/* @endif */}
|
|
||||||
{rowData.map(({ title, route, link, icon, help, pinnedUrls: pinUrls, options = {} }, index) => {
|
{rowData.map(({ title, route, link, icon, help, pinnedUrls: pinUrls, options = {} }, index) => {
|
||||||
// add pins here
|
// add pins here
|
||||||
return getRowElements(title, route, link, icon, help, options, index, pinUrls);
|
return getRowElements(title, route, link, icon, help, options, index, pinUrls);
|
||||||
})}
|
})}
|
||||||
{/* @if TARGET='web' */}
|
|
||||||
<Pixel type={'retargeting'} />
|
|
||||||
{/* @endif */}
|
|
||||||
</Page>
|
</Page>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,12 +1,10 @@
|
||||||
// @flow
|
// @flow
|
||||||
import { SIMPLE_SITE, SHOW_ADS } from 'config';
|
|
||||||
import React, { useEffect } from 'react';
|
import React, { useEffect } from 'react';
|
||||||
import Lbry from 'lbry';
|
import Lbry from 'lbry';
|
||||||
import { parseURI, isNameValid } from 'util/lbryURI';
|
import { parseURI, isNameValid } from 'util/lbryURI';
|
||||||
import ClaimList from 'component/claimList';
|
import ClaimList from 'component/claimList';
|
||||||
import Page from 'component/page';
|
import Page from 'component/page';
|
||||||
import SearchOptions from 'component/searchOptions';
|
import SearchOptions from 'component/searchOptions';
|
||||||
import Ads from 'web/component/ads';
|
|
||||||
import SearchTopClaim from 'component/searchTopClaim';
|
import SearchTopClaim from 'component/searchTopClaim';
|
||||||
import { formatLbryUrlForWeb } from 'util/url';
|
import { formatLbryUrlForWeb } from 'util/url';
|
||||||
import { useHistory } from 'react-router';
|
import { useHistory } from 'react-router';
|
||||||
|
@ -23,7 +21,7 @@ type Props = {
|
||||||
};
|
};
|
||||||
|
|
||||||
export default function SearchPage(props: Props) {
|
export default function SearchPage(props: Props) {
|
||||||
const { urlQuery, searchOptions, search, uris, isSearching, isAuthenticated, hasReachedMaxResultsLength } = props;
|
const { urlQuery, searchOptions, search, uris, isSearching, hasReachedMaxResultsLength } = props;
|
||||||
const { push } = useHistory();
|
const { push } = useHistory();
|
||||||
const [from, setFrom] = React.useState(0);
|
const [from, setFrom] = React.useState(0);
|
||||||
|
|
||||||
|
@ -90,16 +88,7 @@ export default function SearchPage(props: Props) {
|
||||||
// needs to be unique to indicate when a fetch is needed.
|
// needs to be unique to indicate when a fetch is needed.
|
||||||
page={from + 1}
|
page={from + 1}
|
||||||
pageSize={SEARCH_PAGE_SIZE}
|
pageSize={SEARCH_PAGE_SIZE}
|
||||||
header={
|
header={<SearchOptions additionalOptions={searchOptions} onSearchOptionsChanged={resetPage} />}
|
||||||
<SearchOptions
|
|
||||||
simple={SIMPLE_SITE}
|
|
||||||
additionalOptions={searchOptions}
|
|
||||||
onSearchOptionsChanged={resetPage}
|
|
||||||
/>
|
|
||||||
}
|
|
||||||
injectedItem={
|
|
||||||
SHOW_ADS && IS_WEB ? (SIMPLE_SITE ? false : !isAuthenticated && <Ads small type={'video'} />) : false
|
|
||||||
}
|
|
||||||
/>
|
/>
|
||||||
|
|
||||||
<div className="main--empty help">{__('These search results are provided by LBRY, Inc.')}</div>
|
<div className="main--empty help">{__('These search results are provided by LBRY, Inc.')}</div>
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
// @flow
|
// @flow
|
||||||
import { DOMAIN, ENABLE_NO_SOURCE_CLAIMS } from 'config';
|
import { ENABLE_NO_SOURCE_CLAIMS } from 'config';
|
||||||
import * as PAGES from 'constants/pages';
|
import * as PAGES from 'constants/pages';
|
||||||
import React, { useEffect } from 'react';
|
import React, { useEffect } from 'react';
|
||||||
import { lazyImport } from 'util/lazyImport';
|
import { lazyImport } from 'util/lazyImport';
|
||||||
|
@ -19,7 +19,6 @@ const AbandonedChannelPreview = lazyImport(() =>
|
||||||
const FilePage = lazyImport(() => import('page/file' /* webpackChunkName: "filePage" */));
|
const FilePage = lazyImport(() => import('page/file' /* webpackChunkName: "filePage" */));
|
||||||
const LivestreamPage = lazyImport(() => import('page/livestream' /* webpackChunkName: "livestream" */));
|
const LivestreamPage = lazyImport(() => import('page/livestream' /* webpackChunkName: "livestream" */));
|
||||||
const Yrbl = lazyImport(() => import('component/yrbl' /* webpackChunkName: "yrbl" */));
|
const Yrbl = lazyImport(() => import('component/yrbl' /* webpackChunkName: "yrbl" */));
|
||||||
const isDev = process.env.NODE_ENV !== 'production';
|
|
||||||
|
|
||||||
type Props = {
|
type Props = {
|
||||||
isResolvingUri: boolean,
|
isResolvingUri: boolean,
|
||||||
|
@ -84,25 +83,6 @@ function ShowPage(props: Props) {
|
||||||
}, [isCollection, resolvedCollection, collectionId, fetchCollectionItems]);
|
}, [isCollection, resolvedCollection, collectionId, fetchCollectionItems]);
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
// @if TARGET='web'
|
|
||||||
if (canonicalUrl) {
|
|
||||||
const canonicalUrlPath = '/' + canonicalUrl.replace(/^lbry:\/\//, '').replace(/#/g, ':');
|
|
||||||
// Only redirect if we are in lbry.tv land
|
|
||||||
// replaceState will fail if on a different domain (like webcache.googleusercontent.com)
|
|
||||||
const hostname = isDev ? 'localhost' : DOMAIN;
|
|
||||||
if (canonicalUrlPath !== window.location.pathname && hostname === window.location.hostname) {
|
|
||||||
const urlParams = new URLSearchParams(search);
|
|
||||||
let replaceUrl = canonicalUrlPath;
|
|
||||||
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);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
// @endif
|
|
||||||
|
|
||||||
if (
|
if (
|
||||||
(resolveUri && !isResolvingUri && uri && haventFetchedYet) ||
|
(resolveUri && !isResolvingUri && uri && haventFetchedYet) ||
|
||||||
(claimExists && !claimIsPending && (!canonicalUrl || isMine === undefined))
|
(claimExists && !claimIsPending && (!canonicalUrl || isMine === undefined))
|
||||||
|
|
|
@ -8,9 +8,6 @@ import Button from 'component/button';
|
||||||
import { Lbryio } from 'lbryinc';
|
import { Lbryio } from 'lbryinc';
|
||||||
import I18nMessage from 'component/i18nMessage';
|
import I18nMessage from 'component/i18nMessage';
|
||||||
import Card from 'component/common/card';
|
import Card from 'component/common/card';
|
||||||
// @if TARGET='web'
|
|
||||||
import Pixel from 'web/component/pixel';
|
|
||||||
// @endif
|
|
||||||
type Props = {
|
type Props = {
|
||||||
history: { push: (string) => void, location: { search: string } },
|
history: { push: (string) => void, location: { search: string } },
|
||||||
doToast: ({}) => void,
|
doToast: ({}) => void,
|
||||||
|
@ -134,9 +131,6 @@ function SignInVerifyPage(props: Props) {
|
||||||
}
|
}
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
{/* @if TARGET='web' */}
|
|
||||||
<Pixel type={'kill'} />
|
|
||||||
{/* @endif */}
|
|
||||||
</Page>
|
</Page>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
|
@ -9,7 +9,6 @@ import * as CS from 'constants/claim_search';
|
||||||
import Button from 'component/button';
|
import Button from 'component/button';
|
||||||
import I18nMessage from 'component/i18nMessage';
|
import I18nMessage from 'component/i18nMessage';
|
||||||
import * as PAGES from 'constants/pages';
|
import * as PAGES from 'constants/pages';
|
||||||
import { SIMPLE_SITE } from 'config';
|
|
||||||
|
|
||||||
type Props = {
|
type Props = {
|
||||||
name: string,
|
name: string,
|
||||||
|
@ -28,7 +27,6 @@ function TopPage(props: Props) {
|
||||||
name={channelActive ? `@${queryName}` : queryName}
|
name={channelActive ? `@${queryName}` : queryName}
|
||||||
defaultFreshness={CS.FRESH_ALL}
|
defaultFreshness={CS.FRESH_ALL}
|
||||||
defaultOrderBy={CS.ORDER_BY_TOP}
|
defaultOrderBy={CS.ORDER_BY_TOP}
|
||||||
streamType={SIMPLE_SITE ? CS.CONTENT_ALL : undefined}
|
|
||||||
meta={
|
meta={
|
||||||
<div className="search__top-links">
|
<div className="search__top-links">
|
||||||
<I18nMessage
|
<I18nMessage
|
||||||
|
|
|
@ -1,21 +1,10 @@
|
||||||
// @flow
|
// @flow
|
||||||
import React from 'react';
|
import React from 'react';
|
||||||
import { useHistory } from 'react-router';
|
import { useHistory } from 'react-router';
|
||||||
import WalletBalance from 'component/walletBalance';
|
|
||||||
import TxoList from 'component/txoList';
|
import TxoList from 'component/txoList';
|
||||||
import Page from 'component/page';
|
import Page from 'component/page';
|
||||||
import * as PAGES from 'constants/pages';
|
|
||||||
import Spinner from 'component/spinner';
|
import Spinner from 'component/spinner';
|
||||||
import YrblWalletEmpty from 'component/yrblWalletEmpty';
|
import YrblWalletEmpty from 'component/yrblWalletEmpty';
|
||||||
import { Tabs, TabList, Tab, TabPanels, TabPanel } from 'component/common/tabs';
|
|
||||||
|
|
||||||
const TAB_QUERY = 'tab';
|
|
||||||
|
|
||||||
const TABS = {
|
|
||||||
LBRY_CREDITS_TAB: 'credits',
|
|
||||||
ACCOUNT_HISTORY: 'fiat-account-history',
|
|
||||||
PAYMENT_HISTORY: 'fiat-payment-history',
|
|
||||||
};
|
|
||||||
|
|
||||||
type Props = {
|
type Props = {
|
||||||
history: { action: string, push: (string) => void, replace: (string) => void },
|
history: { action: string, push: (string) => void, replace: (string) => void },
|
||||||
|
@ -26,95 +15,13 @@ type Props = {
|
||||||
const WalletPage = (props: Props) => {
|
const WalletPage = (props: Props) => {
|
||||||
const {
|
const {
|
||||||
location: { search },
|
location: { search },
|
||||||
push,
|
|
||||||
} = useHistory();
|
} = useHistory();
|
||||||
|
|
||||||
// @if TARGET='web'
|
|
||||||
const urlParams = new URLSearchParams(search);
|
|
||||||
|
|
||||||
const currentView = urlParams.get(TAB_QUERY) || TABS.LBRY_CREDITS_TAB;
|
|
||||||
|
|
||||||
let tabIndex;
|
|
||||||
switch (currentView) {
|
|
||||||
case TABS.LBRY_CREDITS_TAB:
|
|
||||||
tabIndex = 0;
|
|
||||||
break;
|
|
||||||
case TABS.PAYMENT_HISTORY:
|
|
||||||
tabIndex = 1;
|
|
||||||
break;
|
|
||||||
case TABS.ACCOUNT_HISTORY:
|
|
||||||
tabIndex = 2;
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
tabIndex = 0;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
function onTabChange(newTabIndex) {
|
|
||||||
let url = `/$/${PAGES.WALLET}?`;
|
|
||||||
|
|
||||||
if (newTabIndex === 0) {
|
|
||||||
url += `${TAB_QUERY}=${TABS.LBRY_CREDITS_TAB}`;
|
|
||||||
} else if (newTabIndex === 1) {
|
|
||||||
url += `${TAB_QUERY}=${TABS.PAYMENT_HISTORY}`;
|
|
||||||
} else if (newTabIndex === 2) {
|
|
||||||
url += `${TAB_QUERY}=${TABS.ACCOUNT_HISTORY}`;
|
|
||||||
} else {
|
|
||||||
url += `${TAB_QUERY}=${TABS.LBRY_CREDITS_TAB}`;
|
|
||||||
}
|
|
||||||
push(url);
|
|
||||||
}
|
|
||||||
|
|
||||||
// @endif
|
|
||||||
|
|
||||||
const { totalBalance } = props;
|
const { totalBalance } = props;
|
||||||
const showIntro = totalBalance === 0;
|
const showIntro = totalBalance === 0;
|
||||||
const loading = totalBalance === undefined;
|
const loading = totalBalance === undefined;
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
|
||||||
{/* @if TARGET='web' */}
|
|
||||||
<Page>
|
|
||||||
<Tabs onChange={onTabChange} index={tabIndex}>
|
|
||||||
<TabList className="tabs__list--collection-edit-page">
|
|
||||||
<Tab>{__('Balance')}</Tab>
|
|
||||||
<Tab>{__('Transactions')}</Tab>
|
|
||||||
</TabList>
|
|
||||||
<TabPanels>
|
|
||||||
{/* balances for lbc and fiat */}
|
|
||||||
<TabPanel>
|
|
||||||
<WalletBalance />
|
|
||||||
</TabPanel>
|
|
||||||
{/* transactions panel */}
|
|
||||||
<TabPanel>
|
|
||||||
<div className="section card-stack">
|
|
||||||
<div className="lbc-transactions">
|
|
||||||
{/* if the transactions are loading */}
|
|
||||||
{loading && (
|
|
||||||
<div className="main--empty">
|
|
||||||
<Spinner delayed />
|
|
||||||
</div>
|
|
||||||
)}
|
|
||||||
{/* when the transactions are finished loading */}
|
|
||||||
{!loading && (
|
|
||||||
<>
|
|
||||||
{showIntro ? (
|
|
||||||
<YrblWalletEmpty includeWalletLink />
|
|
||||||
) : (
|
|
||||||
<div className="card-stack">
|
|
||||||
<TxoList search={search} />
|
|
||||||
</div>
|
|
||||||
)}
|
|
||||||
</>
|
|
||||||
)}
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</TabPanel>
|
|
||||||
</TabPanels>
|
|
||||||
</Tabs>
|
|
||||||
</Page>
|
|
||||||
{/* @endif */}
|
|
||||||
{/* @if TARGET='app' */}
|
|
||||||
<Page>
|
<Page>
|
||||||
{loading && (
|
{loading && (
|
||||||
<div className="main--empty">
|
<div className="main--empty">
|
||||||
|
@ -133,8 +40,6 @@ const WalletPage = (props: Props) => {
|
||||||
</>
|
</>
|
||||||
)}
|
)}
|
||||||
</Page>
|
</Page>
|
||||||
{/* @endif */}
|
|
||||||
</>
|
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -9,7 +9,7 @@ import * as MODALS from 'constants/modal_types';
|
||||||
import * as SETTINGS from 'constants/settings';
|
import * as SETTINGS from 'constants/settings';
|
||||||
import * as DAEMON_SETTINGS from 'constants/daemon_settings';
|
import * as DAEMON_SETTINGS from 'constants/daemon_settings';
|
||||||
import * as SHARED_PREFERENCES from 'constants/shared_preferences';
|
import * as SHARED_PREFERENCES from 'constants/shared_preferences';
|
||||||
import { DOMAIN, SIMPLE_SITE } from 'config';
|
import { DOMAIN } from 'config';
|
||||||
import Lbry from 'lbry';
|
import Lbry from 'lbry';
|
||||||
import { doFetchChannelListMine, doFetchCollectionListMine, doCheckPendingClaims } from 'redux/actions/claims';
|
import { doFetchChannelListMine, doFetchCollectionListMine, doCheckPendingClaims } from 'redux/actions/claims';
|
||||||
import { makeSelectClaimForUri, makeSelectClaimIsMine, selectMyChannelClaims } from 'redux/selectors/claims';
|
import { makeSelectClaimForUri, makeSelectClaimIsMine, selectMyChannelClaims } from 'redux/selectors/claims';
|
||||||
|
@ -522,7 +522,7 @@ export function doAnalyticsTagSync() {
|
||||||
}
|
}
|
||||||
|
|
||||||
export function doAnaltyicsPurchaseEvent(fileInfo) {
|
export function doAnaltyicsPurchaseEvent(fileInfo) {
|
||||||
return (dispatch) => {
|
return () => {
|
||||||
let purchasePrice = fileInfo.purchase_receipt && fileInfo.purchase_receipt.amount;
|
let purchasePrice = fileInfo.purchase_receipt && fileInfo.purchase_receipt.amount;
|
||||||
if (purchasePrice) {
|
if (purchasePrice) {
|
||||||
const purchaseInt = Number(Number(purchasePrice).toFixed(0));
|
const purchaseInt = Number(Number(purchasePrice).toFixed(0));
|
||||||
|
@ -535,7 +535,7 @@ export function doSignIn() {
|
||||||
return (dispatch, getState) => {
|
return (dispatch, getState) => {
|
||||||
const state = getState();
|
const state = getState();
|
||||||
const user = selectUser(state);
|
const user = selectUser(state);
|
||||||
const notificationsEnabled = SIMPLE_SITE || user.experimental_ui;
|
const notificationsEnabled = user.experimental_ui; // what is notifications?
|
||||||
|
|
||||||
dispatch(doNotificationSocketConnect(notificationsEnabled));
|
dispatch(doNotificationSocketConnect(notificationsEnabled));
|
||||||
|
|
||||||
|
|
|
@ -6,10 +6,9 @@ import Lbry from 'lbry';
|
||||||
import { doWalletEncrypt, doWalletDecrypt } from 'redux/actions/wallet';
|
import { doWalletEncrypt, doWalletDecrypt } from 'redux/actions/wallet';
|
||||||
import { selectGetSyncIsPending, selectSetSyncIsPending, selectSyncIsLocked } from 'redux/selectors/sync';
|
import { selectGetSyncIsPending, selectSetSyncIsPending, selectSyncIsLocked } from 'redux/selectors/sync';
|
||||||
import { makeSelectClientSetting } from 'redux/selectors/settings';
|
import { makeSelectClientSetting } from 'redux/selectors/settings';
|
||||||
import { getSavedPassword, getAuthToken } from 'util/saved-passwords';
|
import { getSavedPassword } from 'util/saved-passwords';
|
||||||
import { doAnalyticsTagSync, doHandleSyncComplete } from 'redux/actions/app';
|
import { doAnalyticsTagSync, doHandleSyncComplete } from 'redux/actions/app';
|
||||||
import { selectUserVerifiedEmail } from 'redux/selectors/user';
|
import { selectUserVerifiedEmail } from 'redux/selectors/user';
|
||||||
import { X_LBRY_AUTH_TOKEN } from 'constants/token';
|
|
||||||
|
|
||||||
let syncTimer = null;
|
let syncTimer = null;
|
||||||
const SYNC_INTERVAL = 1000 * 60 * 5; // 5 minutes
|
const SYNC_INTERVAL = 1000 * 60 * 5; // 5 minutes
|
||||||
|
@ -155,17 +154,6 @@ export function doGetSync(passedPassword?: string, callback?: (any, ?boolean) =>
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// @if TARGET='web'
|
|
||||||
const xAuth =
|
|
||||||
Lbry.getApiRequestHeaders() && Object.keys(Lbry.getApiRequestHeaders()).includes(X_LBRY_AUTH_TOKEN)
|
|
||||||
? Lbry.getApiRequestHeaders()[X_LBRY_AUTH_TOKEN]
|
|
||||||
: '';
|
|
||||||
if (xAuth && xAuth !== getAuthToken()) {
|
|
||||||
window.location.reload();
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
// @endif
|
|
||||||
|
|
||||||
return (dispatch: Dispatch) => {
|
return (dispatch: Dispatch) => {
|
||||||
dispatch({
|
dispatch({
|
||||||
type: ACTIONS.GET_SYNC_STARTED,
|
type: ACTIONS.GET_SYNC_STARTED,
|
||||||
|
|
|
@ -4,7 +4,7 @@ import * as SHARED_PREFERENCES from 'constants/shared_preferences';
|
||||||
import moment from 'moment';
|
import moment from 'moment';
|
||||||
import { getSubsetFromKeysArray } from 'util/sync-settings';
|
import { getSubsetFromKeysArray } from 'util/sync-settings';
|
||||||
import { getDefaultLanguage } from 'util/default-languages';
|
import { getDefaultLanguage } from 'util/default-languages';
|
||||||
import { UNSYNCED_SETTINGS, SIMPLE_SITE } from 'config';
|
import { UNSYNCED_SETTINGS } from 'config';
|
||||||
import Comments from 'comments';
|
import Comments from 'comments';
|
||||||
|
|
||||||
const { CLIENT_SYNC_KEYS } = SHARED_PREFERENCES;
|
const { CLIENT_SYNC_KEYS } = SHARED_PREFERENCES;
|
||||||
|
@ -73,7 +73,7 @@ const defaultState = {
|
||||||
[SETTINGS.AUTOPLAY_MEDIA]: true,
|
[SETTINGS.AUTOPLAY_MEDIA]: true,
|
||||||
[SETTINGS.FLOATING_PLAYER]: true,
|
[SETTINGS.FLOATING_PLAYER]: true,
|
||||||
[SETTINGS.AUTO_DOWNLOAD]: true,
|
[SETTINGS.AUTO_DOWNLOAD]: true,
|
||||||
[SETTINGS.HIDE_REPOSTS]: SIMPLE_SITE,
|
[SETTINGS.HIDE_REPOSTS]: false,
|
||||||
|
|
||||||
// OS
|
// OS
|
||||||
[SETTINGS.AUTO_LAUNCH]: true,
|
[SETTINGS.AUTO_LAUNCH]: true,
|
||||||
|
|
|
@ -17,7 +17,6 @@ import { createNormalizedSearchKey, getRecommendationSearchOptions } from 'util/
|
||||||
import { selectMutedChannels } from 'redux/selectors/blocked';
|
import { selectMutedChannels } from 'redux/selectors/blocked';
|
||||||
import { selectHistory } from 'redux/selectors/content';
|
import { selectHistory } from 'redux/selectors/content';
|
||||||
import { selectAllCostInfoByUri } from 'lbryinc';
|
import { selectAllCostInfoByUri } from 'lbryinc';
|
||||||
import { SIMPLE_SITE } from 'config';
|
|
||||||
|
|
||||||
type State = { search: SearchState };
|
type State = { search: SearchState };
|
||||||
|
|
||||||
|
@ -89,11 +88,6 @@ export const makeSelectRecommendedContentForUri = (uri: string) =>
|
||||||
isBackgroundSearch?: boolean,
|
isBackgroundSearch?: boolean,
|
||||||
} = { size: 20, nsfw: matureEnabled, isBackgroundSearch: true };
|
} = { size: 20, nsfw: matureEnabled, isBackgroundSearch: true };
|
||||||
|
|
||||||
if (SIMPLE_SITE) {
|
|
||||||
options[SEARCH_OPTIONS.CLAIM_TYPE] = SEARCH_OPTIONS.INCLUDE_FILES;
|
|
||||||
options[SEARCH_OPTIONS.MEDIA_VIDEO] = true;
|
|
||||||
options[SEARCH_OPTIONS.PRICE_FILTER_FREE] = true;
|
|
||||||
}
|
|
||||||
if (matureEnabled || (!matureEnabled && !isMature)) {
|
if (matureEnabled || (!matureEnabled && !isMature)) {
|
||||||
options[SEARCH_OPTIONS.RELATED_TO] = claim.claim_id;
|
options[SEARCH_OPTIONS.RELATED_TO] = claim.claim_id;
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
// @flow
|
// @flow
|
||||||
|
|
||||||
import { isNameValid, isURIValid, normalizeURI, parseURI } from 'util/lbryURI';
|
import { isNameValid, isURIValid, normalizeURI, parseURI } from 'util/lbryURI';
|
||||||
import { URL as SITE_URL, URL_LOCAL, URL_DEV, SIMPLE_SITE } from 'config';
|
import { URL as SITE_URL, URL_LOCAL, URL_DEV } from 'config';
|
||||||
import { SEARCH_OPTIONS } from 'constants/search';
|
import { SEARCH_OPTIONS } from 'constants/search';
|
||||||
|
|
||||||
export function createNormalizedSearchKey(query: string) {
|
export function createNormalizedSearchKey(query: string) {
|
||||||
|
@ -92,12 +92,6 @@ export function getUriForSearchTerm(term: string) {
|
||||||
export function getRecommendationSearchOptions(matureEnabled: boolean, claimIsMature: boolean, claimId: string) {
|
export function getRecommendationSearchOptions(matureEnabled: boolean, claimIsMature: boolean, claimId: string) {
|
||||||
const options = { size: 20, nsfw: matureEnabled, isBackgroundSearch: true };
|
const options = { size: 20, nsfw: matureEnabled, isBackgroundSearch: true };
|
||||||
|
|
||||||
if (SIMPLE_SITE) {
|
|
||||||
options[SEARCH_OPTIONS.CLAIM_TYPE] = SEARCH_OPTIONS.INCLUDE_FILES;
|
|
||||||
options[SEARCH_OPTIONS.MEDIA_VIDEO] = true;
|
|
||||||
options[SEARCH_OPTIONS.PRICE_FILTER_FREE] = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (matureEnabled || !claimIsMature) {
|
if (matureEnabled || !claimIsMature) {
|
||||||
options[SEARCH_OPTIONS.RELATED_TO] = claimId;
|
options[SEARCH_OPTIONS.RELATED_TO] = claimId;
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue