diff --git a/package.json b/package.json index 6fed1a788..ec02d7d8e 100644 --- a/package.json +++ b/package.json @@ -40,6 +40,8 @@ "postinstall": "electron-builder install-app-deps && node ./build/downloadDaemon.js" }, "dependencies": { + "@reach/menu-button": "^0.1.18", + "@reach/tooltip": "^0.2.1", "electron-dl": "^1.11.0", "electron-log": "^2.2.12", "electron-updater": "^4.0.6", @@ -119,7 +121,7 @@ "jsmediatags": "^3.8.1", "json-loader": "^0.5.4", "lbry-format": "https://github.com/lbryio/lbry-format.git", - "lbry-redux": "lbryio/lbry-redux#291324d03f694c4fefa6967aa7be02d9245596a8", + "lbry-redux": "lbryio/lbry-redux#6a447d0542d23b9a37e266f5f85d3bde5297a451", "lbryinc": "lbryio/lbryinc#43d382d9b74d396a581a74d87e4c53105e04f845", "lint-staged": "^7.0.2", "localforage": "^1.7.1", diff --git a/src/ui/component/button/view.jsx b/src/ui/component/button/view.jsx index 4c62c3aab..0949ecdfb 100644 --- a/src/ui/component/button/view.jsx +++ b/src/ui/component/button/view.jsx @@ -105,6 +105,7 @@ class Button extends React.PureComponent { exact to={path} title={title} + disabled={disabled} onClick={e => { e.stopPropagation(); if (onClick) { diff --git a/src/ui/component/channelContent/view.jsx b/src/ui/component/channelContent/view.jsx index a78865815..309664b70 100644 --- a/src/ui/component/channelContent/view.jsx +++ b/src/ui/component/channelContent/view.jsx @@ -1,6 +1,6 @@ // @flow import React, { Fragment } from 'react'; -import FileList from 'component/fileList'; +import ClaimList from 'component/claimList'; import HiddenNsfwClaims from 'component/hiddenNsfwClaims'; import { withRouter } from 'react-router-dom'; import Paginate from 'component/common/paginate'; @@ -35,7 +35,7 @@ function ChannelContent(props: Props) { {!channelIsMine && } - {hasContent && claim.permanent_url)} />} + {hasContent && claim.permanent_url)} />} fetchClaims(uri, page)} diff --git a/src/ui/component/claimList/index.js b/src/ui/component/claimList/index.js new file mode 100644 index 000000000..55ef525f8 --- /dev/null +++ b/src/ui/component/claimList/index.js @@ -0,0 +1,11 @@ +import { connect } from 'react-redux'; +import ClaimList from './view'; + +const select = state => ({}); + +const perform = dispatch => ({}); + +export default connect( + select, + perform +)(ClaimList); diff --git a/src/ui/component/fileList/view.jsx b/src/ui/component/claimList/view.jsx similarity index 73% rename from src/ui/component/fileList/view.jsx rename to src/ui/component/claimList/view.jsx index 6310f171a..7ce272d1f 100644 --- a/src/ui/component/fileList/view.jsx +++ b/src/ui/component/claimList/view.jsx @@ -1,7 +1,8 @@ // @flow -import * as React from 'react'; +import type { Node } from 'react'; +import React from 'react'; import classnames from 'classnames'; -import FileListItem from 'component/fileListItem'; +import ClaimListItem from 'component/claimListItem'; import Spinner from 'component/spinner'; import { FormField } from 'component/common/form'; import usePersistedState from 'util/use-persisted-state'; @@ -11,19 +12,19 @@ const SORT_OLD = 'old'; type Props = { uris: Array, - header: React.Node, - headerAltControls: React.Node, - injectedItem?: React.Node, + header: Node | boolean, + headerAltControls: Node, + injectedItem?: Node, loading: boolean, - noHeader?: boolean, - slim?: string, + type: string, empty?: string, + meta?: Node, // If using the default header, this is a unique ID needed to persist the state of the filter setting persistedStorageKey?: string, }; -export default function FileList(props: Props) { - const { uris, header, headerAltControls, injectedItem, loading, persistedStorageKey, noHeader, slim, empty } = props; +export default function ClaimList(props: Props) { + const { uris, headerAltControls, injectedItem, loading, persistedStorageKey, empty, meta, type, header } = props; const [currentSort, setCurrentSort] = usePersistedState(persistedStorageKey, SORT_NEW); const sortedUris = uris && currentSort === SORT_OLD ? uris.reverse() : uris; const hasUris = uris && !!uris.length; @@ -34,8 +35,8 @@ export default function FileList(props: Props) { return (
- {!noHeader && ( -
+ {header !== false && ( +
{header || ( {headerAltControls}
)} + {meta &&
{meta}
} {hasUris && (
    {sortedUris.map((uri, index) => ( - + {index === 4 && injectedItem &&
  • {injectedItem}
  • }
    ))} diff --git a/src/ui/component/fileListDiscover/index.js b/src/ui/component/claimListDiscover/index.js similarity index 52% rename from src/ui/component/fileListDiscover/index.js rename to src/ui/component/claimListDiscover/index.js index d84f83cfc..8729ef22f 100644 --- a/src/ui/component/fileListDiscover/index.js +++ b/src/ui/component/claimListDiscover/index.js @@ -1,18 +1,18 @@ import { connect } from 'react-redux'; -import { selectFollowedTags, doClaimSearch, selectLastClaimSearchUris, selectFetchingClaimSearch } from 'lbry-redux'; -import FileListDiscover from './view'; +import { doClaimSearch, selectLastClaimSearchUris, selectFetchingClaimSearch, doToggleTagFollow } from 'lbry-redux'; +import ClaimListDiscover from './view'; const select = state => ({ - followedTags: selectFollowedTags(state), uris: selectLastClaimSearchUris(state), loading: selectFetchingClaimSearch(state), }); const perform = { doClaimSearch, + doToggleTagFollow, }; export default connect( select, perform -)(FileListDiscover); +)(ClaimListDiscover); diff --git a/src/ui/component/fileListDiscover/view.jsx b/src/ui/component/claimListDiscover/view.jsx similarity index 79% rename from src/ui/component/fileListDiscover/view.jsx rename to src/ui/component/claimListDiscover/view.jsx index e09dc2162..40f0b7a20 100644 --- a/src/ui/component/fileListDiscover/view.jsx +++ b/src/ui/component/claimListDiscover/view.jsx @@ -1,8 +1,10 @@ // @flow +import type { Node } from 'react'; import React, { useEffect } from 'react'; -import { FormField } from 'component/common/form'; -import FileList from 'component/fileList'; import moment from 'moment'; +import { FormField } from 'component/common/form'; +import ClaimList from 'component/claimList'; +import Tag from 'component/tag'; import usePersistedState from 'util/use-persisted-state'; const TIME_DAY = 'day'; @@ -26,10 +28,12 @@ type Props = { tags: Array, loading: boolean, personal: boolean, + doToggleTagFollow: string => void, + meta?: Node, }; -function FileListDiscover(props: Props) { - const { doClaimSearch, uris, tags, loading, personal, injectedItem } = props; +function ClaimListDiscover(props: Props) { + const { doClaimSearch, uris, tags, loading, personal, injectedItem, meta } = props; const [personalSort, setPersonalSort] = usePersistedState('file-list-trending:personalSort', SEARCH_SORT_YOU); const [typeSort, setTypeSort] = usePersistedState('file-list-trending:typeSort', TYPE_TRENDING); const [timeSort, setTimeSort] = usePersistedState('file-list-trending:timeSort', TIME_WEEK); @@ -40,7 +44,7 @@ function FileListDiscover(props: Props) { const options = {}; const newTags = tagsString.split(','); - if ((tags && !personal) || (tags && personal && personalSort === SEARCH_SORT_YOU)) { + if ((newTags && !personal) || (newTags && personal && personalSort === SEARCH_SORT_YOU)) { options.any_tags = newTags; } @@ -61,19 +65,26 @@ function FileListDiscover(props: Props) { } doClaimSearch(20, options); - }, [personalSort, typeSort, timeSort, doClaimSearch, tagsString]); + }, [personal, personalSort, typeSort, timeSort, doClaimSearch, tagsString]); const header = ( - -

    - {toCapitalCase(typeSort)} {'For'} -

    +

    + setTypeSort(e.target.value)} + > + {SEARCH_TYPES.map(type => ( + + ))} + + {__('For')} {!personal && tags && tags.length ? ( - tags.map(tag => ( - - {tag} - - )) + tags.map(tag => ) ) : ( )} - +

    ); const headerAltControls = ( - setTypeSort(e.target.value)} - > - {SEARCH_TYPES.map(type => ( - - ))} - {typeSort === 'top' && ( +
    + +
    ); } -export default FileListDiscover; +export default ClaimListDiscover; diff --git a/src/ui/component/fileListItem/index.js b/src/ui/component/claimListItem/index.js similarity index 94% rename from src/ui/component/fileListItem/index.js rename to src/ui/component/claimListItem/index.js index 4b6352234..b69db1d6c 100644 --- a/src/ui/component/fileListItem/index.js +++ b/src/ui/component/claimListItem/index.js @@ -10,7 +10,7 @@ import { makeSelectClaimIsNsfw, } from 'lbry-redux'; import { selectShowNsfw } from 'redux/selectors/settings'; -import FileListItem from './view'; +import ClaimListItem from './view'; const select = (state, props) => ({ pending: makeSelectClaimIsPending(props.uri)(state), @@ -30,4 +30,4 @@ const perform = dispatch => ({ export default connect( select, perform -)(FileListItem); +)(ClaimListItem); diff --git a/src/ui/component/fileListItem/view.jsx b/src/ui/component/claimListItem/view.jsx similarity index 90% rename from src/ui/component/fileListItem/view.jsx rename to src/ui/component/claimListItem/view.jsx index 3aff7f9e7..bc2836ce6 100644 --- a/src/ui/component/fileListItem/view.jsx +++ b/src/ui/component/claimListItem/view.jsx @@ -10,7 +10,7 @@ import UriIndicator from 'component/uriIndicator'; import TruncatedText from 'component/common/truncated-text'; import DateTime from 'component/dateTime'; import FileProperties from 'component/fileProperties'; -import FileTags from 'component/fileTags'; +import ClaimTags from 'component/claimTags'; import SubscribeButton from 'component/subscribeButton'; import ChannelThumbnail from 'component/channelThumbnail'; @@ -27,12 +27,11 @@ type Props = { thumbnail: string, title: string, nsfw: boolean, - large: boolean, placeholder: boolean, - slim: boolean, + type: string, }; -function FileListItem(props: Props) { +function ClaimListItem(props: Props) { const { obscureNsfw, claimIsMine, @@ -45,9 +44,8 @@ function FileListItem(props: Props) { nsfw, resolveUri, claim, - large, placeholder, - slim, + type, } = props; const haventFetched = claim === undefined; @@ -98,7 +96,7 @@ function FileListItem(props: Props) { onClick={onClick} onContextMenu={handleContextMenu} className={classnames('file-list__item', { - 'file-list__item--large': large, + 'file-list__item--large': type === 'large', })} > {isChannel ? : } @@ -107,10 +105,10 @@ function FileListItem(props: Props) {
    - {!slim && ( + {type !== 'small' && (
    {isChannel && } - + {!isChannel && }
    )} @@ -122,11 +120,11 @@ function FileListItem(props: Props) {
    {isChannel ? `${claimsInChannel} ${__('publishes')}` : }
    - {!slim && } + ); } -export default withRouter(FileListItem); +export default withRouter(ClaimListItem); diff --git a/src/ui/component/fileTags/index.js b/src/ui/component/claimTags/index.js similarity index 86% rename from src/ui/component/fileTags/index.js rename to src/ui/component/claimTags/index.js index bc63f15d7..0f498f2e3 100644 --- a/src/ui/component/fileTags/index.js +++ b/src/ui/component/claimTags/index.js @@ -1,6 +1,6 @@ import { connect } from 'react-redux'; import { makeSelectTagsForUri, selectFollowedTags } from 'lbry-redux'; -import FileTags from './view'; +import ClaimTags from './view'; const select = (state, props) => ({ tags: makeSelectTagsForUri(props.uri)(state), @@ -10,4 +10,4 @@ const select = (state, props) => ({ export default connect( select, null -)(FileTags); +)(ClaimTags); diff --git a/src/ui/component/fileTags/view.jsx b/src/ui/component/claimTags/view.jsx similarity index 50% rename from src/ui/component/fileTags/view.jsx rename to src/ui/component/claimTags/view.jsx index 969e3d1c0..04470cf7e 100644 --- a/src/ui/component/fileTags/view.jsx +++ b/src/ui/component/claimTags/view.jsx @@ -1,19 +1,24 @@ // @flow import * as React from 'react'; +import classnames from 'classnames'; import Button from 'component/button'; -const MAX_TAGS = 4; +const SLIM_TAGS = 2; +const NORMAL_TAGS = 4; +const LARGE_TAGS = 10; type Props = { tags: Array, followedTags: Array, + type: string, }; -export default function FileTags(props: Props) { - const { tags, followedTags } = props; +export default function ClaimTags(props: Props) { + const { tags, followedTags, type } = props; + const numberOfTags = type === 'small' ? SLIM_TAGS : type === 'large' ? LARGE_TAGS : NORMAL_TAGS; let tagsToDisplay = []; - for (var i = 0; tagsToDisplay.length < MAX_TAGS - 2; i++) { + for (var i = 0; tagsToDisplay.length < numberOfTags - 2; i++) { const tag = followedTags[i]; if (!tag) { break; @@ -28,7 +33,7 @@ export default function FileTags(props: Props) { for (var i = 0; i < sortedTags.length; i++) { const tag = sortedTags[i]; - if (!tag || tagsToDisplay.length === MAX_TAGS) { + if (!tag || tagsToDisplay.length === numberOfTags) { break; } @@ -38,11 +43,9 @@ export default function FileTags(props: Props) { } return ( -
    +
    {tagsToDisplay.map(tag => ( - +
    ); diff --git a/src/ui/component/copyableText/view.jsx b/src/ui/component/copyableText/view.jsx index 1ac15adce..5a292719c 100644 --- a/src/ui/component/copyableText/view.jsx +++ b/src/ui/component/copyableText/view.jsx @@ -44,7 +44,7 @@ export default class CopyableText extends React.PureComponent { onFocus={this.onFocus} inputButton={
    ); diff --git a/src/ui/component/header/index.js b/src/ui/component/header/index.js index cb969e585..391bb7226 100644 --- a/src/ui/component/header/index.js +++ b/src/ui/component/header/index.js @@ -1,21 +1,21 @@ +import * as SETTINGS from 'constants/settings'; import { connect } from 'react-redux'; -import { selectBalance, SETTINGS } from 'lbry-redux'; +import { selectBalance, SETTINGS as LBRY_REDUX_SETTINGS } from 'lbry-redux'; import { formatCredits } from 'util/format-credits'; -import { selectIsUpgradeAvailable, selectAutoUpdateDownloaded } from 'redux/selectors/app'; -import { doDownloadUpgradeRequested } from 'redux/actions/app'; -import Header from './view'; +import { doSetClientSetting } from 'redux/actions/settings'; import { makeSelectClientSetting } from 'redux/selectors/settings'; +import Header from './view'; const select = state => ({ - autoUpdateDownloaded: selectAutoUpdateDownloaded(state), balance: selectBalance(state), - language: makeSelectClientSetting(SETTINGS.LANGUAGE)(state), // trigger redraw on language change - isUpgradeAvailable: selectIsUpgradeAvailable(state), + language: makeSelectClientSetting(LBRY_REDUX_SETTINGS.LANGUAGE)(state), // trigger redraw on language change roundedBalance: formatCredits(selectBalance(state) || 0, 2), + currentTheme: makeSelectClientSetting(SETTINGS.THEME)(state), + automaticDarkModeEnabled: makeSelectClientSetting(SETTINGS.AUTOMATIC_DARK_MODE_ENABLED)(state), }); const perform = dispatch => ({ - downloadUpgradeRequested: () => dispatch(doDownloadUpgradeRequested()), + setClientSetting: (key, value) => dispatch(doSetClientSetting(key, value)), }); export default connect( diff --git a/src/ui/component/header/view.jsx b/src/ui/component/header/view.jsx index 45dedef07..afce53895 100644 --- a/src/ui/component/header/view.jsx +++ b/src/ui/component/header/view.jsx @@ -1,9 +1,13 @@ // @flow import * as ICONS from 'constants/icons'; +import * as SETTINGS from 'constants/settings'; import * as React from 'react'; +import { withRouter } from 'react-router'; import Button from 'component/button'; import LbcSymbol from 'component/common/lbc-symbol'; import WunderBar from 'component/wunderbar'; +import Icon from 'component/common/icon'; +import { Menu, MenuList, MenuButton, MenuItem } from '@reach/menu-button'; type Props = { autoUpdateDownloaded: boolean, @@ -11,16 +15,29 @@ type Props = { isUpgradeAvailable: boolean, roundedBalance: number, downloadUpgradeRequested: any => void, + history: { push: string => void }, + currentTheme: string, + automaticDarkModeEnabled: boolean, + setClientSetting: (string, boolean | string) => void, }; const Header = (props: Props) => { - const { autoUpdateDownloaded, downloadUpgradeRequested, isUpgradeAvailable, roundedBalance } = props; + const { roundedBalance, history, setClientSetting, currentTheme, automaticDarkModeEnabled } = props; - const showUpgradeButton = autoUpdateDownloaded || (process.platform === 'linux' && isUpgradeAvailable); + function handleThemeToggle() { + if (automaticDarkModeEnabled) { + setClientSetting(SETTINGS.AUTOMATIC_DARK_MODE_ENABLED, false); + } + + if (currentTheme === 'dark') { + setClientSetting(SETTINGS.THEME, 'light'); + } else { + setClientSetting(SETTINGS.THEME, 'dark'); + } + } return (
    -
    ); }; -export default Header; +export default withRouter(Header); diff --git a/src/ui/component/inviteNew/view.jsx b/src/ui/component/inviteNew/view.jsx index 0b1631d2d..7d8a38d95 100644 --- a/src/ui/component/inviteNew/view.jsx +++ b/src/ui/component/inviteNew/view.jsx @@ -1,7 +1,7 @@ // @flow import React from 'react'; import Button from 'component/button'; -import { Form, FormField, Submit } from 'component/common/form'; +import { Form, FormField } from 'component/common/form'; import CopyableText from 'component/copyableText'; type FormProps = { @@ -48,7 +48,7 @@ class FormInviteNew extends React.PureComponent { name="email" value={this.state.email} error={errorMessage} - inputButton={} + inputButton={
diff --git a/src/ui/component/rewardTile/view.jsx b/src/ui/component/rewardTile/view.jsx index 268c53083..7a4ca3c4c 100644 --- a/src/ui/component/rewardTile/view.jsx +++ b/src/ui/component/rewardTile/view.jsx @@ -33,10 +33,10 @@ const RewardTile = (props: Props) => {
{reward.reward_type === rewards.TYPE_GENERATED_CODE && ( - +
+ + + {!slim && !!transactions.length && ( +
+
{
- )} -
- {!transactionList.length &&

{emptyMessage || __('No transactions to list.')}

} + + )} + + {!loading && !transactionList.length && ( +

{emptyMessage || __('No transactions.')}

+ )} {!!transactionList.length && ( diff --git a/src/ui/component/transactionListRecent/index.js b/src/ui/component/transactionListRecent/index.js index bb4bdb5b2..8c19d56a0 100644 --- a/src/ui/component/transactionListRecent/index.js +++ b/src/ui/component/transactionListRecent/index.js @@ -1,17 +1,9 @@ import { connect } from 'react-redux'; -import { - doFetchTransactions, - selectRecentTransactions, - selectHasTransactions, - selectIsFetchingTransactions, - doFetchClaimListMine, -} from 'lbry-redux'; +import { doFetchTransactions, selectRecentTransactions, doFetchClaimListMine } from 'lbry-redux'; import TransactionListRecent from './view'; const select = state => ({ - fetchingTransactions: selectIsFetchingTransactions(state), transactions: selectRecentTransactions(state), - hasTransactions: selectHasTransactions(state), }); const perform = dispatch => ({ diff --git a/src/ui/component/transactionListRecent/view.jsx b/src/ui/component/transactionListRecent/view.jsx index 09994bc85..97ae378b7 100644 --- a/src/ui/component/transactionListRecent/view.jsx +++ b/src/ui/component/transactionListRecent/view.jsx @@ -1,10 +1,6 @@ // @flow -import * as icons from 'constants/icons'; -import React, { Fragment } from 'react'; -import BusyIndicator from 'component/common/busy-indicator'; -import Button from 'component/button'; +import React from 'react'; import TransactionList from 'component/transactionList'; -import RefreshTransactionButton from 'component/transactionRefreshButton'; type Props = { fetchTransactions: () => void, @@ -23,42 +19,15 @@ class TransactionListRecent extends React.PureComponent { } render() { - const { fetchingTransactions, hasTransactions, transactions } = this.props; + const { transactions } = this.props; return ( -
-
-

- {__('Recent Transactions')} - -

-
- - {fetchingTransactions && !hasTransactions && ( -
- -
- )} - - {!fetchingTransactions && !hasTransactions && ( -
-

{__('No transactions.')}

-
- )} - - {hasTransactions && ( - -
- -
-
-
-
- )} +
+
); } diff --git a/src/ui/component/userEmail/index.js b/src/ui/component/userEmail/index.js new file mode 100644 index 000000000..4fdc00f92 --- /dev/null +++ b/src/ui/component/userEmail/index.js @@ -0,0 +1,18 @@ +import { connect } from 'react-redux'; +import { selectEmailToVerify, doUserResendVerificationEmail, doUserCheckEmailVerified, selectUser } from 'lbryinc'; +import UserEmailVerify from './view'; + +const select = state => ({ + email: selectEmailToVerify(state), + user: selectUser(state), +}); + +const perform = dispatch => ({ + resendVerificationEmail: email => dispatch(doUserResendVerificationEmail(email)), + checkEmailVerified: () => dispatch(doUserCheckEmailVerified()), +}); + +export default connect( + select, + perform +)(UserEmailVerify); diff --git a/src/ui/component/userEmail/view.jsx b/src/ui/component/userEmail/view.jsx new file mode 100644 index 000000000..eaa413476 --- /dev/null +++ b/src/ui/component/userEmail/view.jsx @@ -0,0 +1,60 @@ +// @flow +import * as React from 'react'; +import Button from 'component/button'; +import { FormField } from 'component/common/form'; +import UserEmailNew from 'component/userEmailNew'; +import UserEmailVerify from 'component/userEmailVerify'; + +type Props = { + cancelButton: React.Node, + email: string, + resendVerificationEmail: string => void, + checkEmailVerified: () => void, + user: { + has_verified_email: boolean, + }, +}; + +function UserEmail(props: Props) { + const { email, user } = props; + let isVerified = false; + if (user) { + isVerified = user.has_verified_email; + } + + return ( +
+ {!email && } + {user && email && !isVerified && } + {email && isVerified && ( + +
+

{__('Email')}

+

+ {email && isVerified && __('Your email has been successfully verified')} + {!email && __('')}. +

+
+ + {isVerified && ( + } + /> + )} +

+ {`${__( + 'This information is disclosed only to LBRY, Inc. and not to the LBRY network. It is only required to earn LBRY rewards.' + )} `} +

+
+ )} +
+ ); +} + +export default UserEmail; diff --git a/src/ui/component/userEmailNew/view.jsx b/src/ui/component/userEmailNew/view.jsx index 57976e85b..99cda26e9 100644 --- a/src/ui/component/userEmailNew/view.jsx +++ b/src/ui/component/userEmailNew/view.jsx @@ -72,6 +72,7 @@ class UserEmailNew extends React.PureComponent { />
{cancelButton}
+

{__('Your email address will never be sold and you can unsubscribe at any time.')}

); } diff --git a/src/ui/component/userEmailVerify/view.jsx b/src/ui/component/userEmailVerify/view.jsx index 2c6cc9fec..d196844f6 100644 --- a/src/ui/component/userEmailVerify/view.jsx +++ b/src/ui/component/userEmailVerify/view.jsx @@ -56,7 +56,7 @@ class UserEmailVerify extends React.PureComponent {
-

+

{__('An email was sent to')} {email}.{' '} {__('Follow the link and you will be good to go. This will update automatically.')}

diff --git a/src/ui/component/walletAddress/view.jsx b/src/ui/component/walletAddress/view.jsx index 5ec6a418c..7c5083f7c 100644 --- a/src/ui/component/walletAddress/view.jsx +++ b/src/ui/component/walletAddress/view.jsx @@ -1,5 +1,4 @@ // @flow -import * as icons from 'constants/icons'; import React from 'react'; import Button from 'component/button'; import CopyableText from 'component/copyableText'; @@ -27,7 +26,7 @@ class WalletAddress extends React.PureComponent { (this: any).toggleQR = this.toggleQR.bind(this); } - componentWillMount() { + componentDidMount() { const { checkAddressIsMine, receiveAddress, getNewAddress } = this.props; if (!receiveAddress) { getNewAddress(); @@ -62,9 +61,8 @@ class WalletAddress extends React.PureComponent {
); diff --git a/src/ui/component/walletSend/view.jsx b/src/ui/component/walletSend/view.jsx index 199b57370..6a45bb1f8 100644 --- a/src/ui/component/walletSend/view.jsx +++ b/src/ui/component/walletSend/view.jsx @@ -1,6 +1,6 @@ // @flow -import React from 'react'; import * as MODALS from 'constants/modal_types'; +import React from 'react'; import Button from 'component/button'; import { Form, FormField } from 'component/common/form'; import { Formik } from 'formik'; @@ -82,7 +82,7 @@ class WalletSend extends React.PureComponent {

{title}

-
- {isRewardContent && ( - - )} - {nsfw &&
MATURE
} - -
-
@@ -304,11 +280,42 @@ class FilePage extends React.Component {
+
+ +
+
+
diff --git a/src/ui/page/fileListDownloaded/view.jsx b/src/ui/page/fileListDownloaded/view.jsx index 325e33e34..ad48d5bcf 100644 --- a/src/ui/page/fileListDownloaded/view.jsx +++ b/src/ui/page/fileListDownloaded/view.jsx @@ -1,7 +1,7 @@ // @flow import React from 'react'; import Button from 'component/button'; -import FileList from 'component/fileList'; +import ClaimList from 'component/claimList'; type Props = { fetching: boolean, @@ -18,7 +18,7 @@ function FileListDownloaded(props: Props) { {hasDownloads ? (
- +
) : (
diff --git a/src/ui/page/fileListPublished/view.jsx b/src/ui/page/fileListPublished/view.jsx index 30ddc7f62..bb98f9c58 100644 --- a/src/ui/page/fileListPublished/view.jsx +++ b/src/ui/page/fileListPublished/view.jsx @@ -1,7 +1,7 @@ // @flow import React, { useEffect } from 'react'; import Button from 'component/button'; -import FileList from 'component/fileList'; +import ClaimList from 'component/claimList'; import Page from 'component/page'; type Props = { @@ -21,7 +21,7 @@ function FileListPublished(props: Props) { {uris && uris.length ? (
- +
) : (
diff --git a/src/ui/page/help/view.jsx b/src/ui/page/help/view.jsx index e71079928..924120d34 100644 --- a/src/ui/page/help/view.jsx +++ b/src/ui/page/help/view.jsx @@ -130,7 +130,7 @@ class HelpPage extends React.PureComponent {
-
@@ -147,7 +147,7 @@ class HelpPage extends React.PureComponent {
-
@@ -167,7 +167,7 @@ class HelpPage extends React.PureComponent { navigate="/$/report" label={__('Submit a Bug Report/Feature Request')} icon={icons.REPORT} - button="primary" + button="inverse" />
@@ -188,8 +188,8 @@ class HelpPage extends React.PureComponent {
-
@@ -198,8 +198,8 @@ class HelpPage extends React.PureComponent { {/* @endif */} -
-
+
+

{__('About')}

{this.state.upgradeAvailable !== null && this.state.upgradeAvailable ? ( diff --git a/src/ui/page/invite/view.jsx b/src/ui/page/invite/view.jsx index a4929a9cc..ae5c832dc 100644 --- a/src/ui/page/invite/view.jsx +++ b/src/ui/page/invite/view.jsx @@ -3,7 +3,6 @@ import React from 'react'; import BusyIndicator from 'component/common/busy-indicator'; import InviteNew from 'component/inviteNew'; import InviteList from 'component/inviteList'; -import Page from 'component/page'; type Props = { isPending: boolean, @@ -27,7 +26,7 @@ class InvitePage extends React.PureComponent { const { isPending, isFailed } = this.props; return ( - +
{isPending && } {!isPending && isFailed && {__('Failed to retrieve invite status.')}} {!isPending && !isFailed && ( @@ -36,7 +35,7 @@ class InvitePage extends React.PureComponent { )} - +
); } } diff --git a/src/ui/page/rewards/view.jsx b/src/ui/page/rewards/view.jsx index 81d461e5a..9001a2781 100644 --- a/src/ui/page/rewards/view.jsx +++ b/src/ui/page/rewards/view.jsx @@ -129,7 +129,7 @@ class RewardsPage extends PureComponent {

-
{this.renderCustomRewardCode()}
+
{this.renderCustomRewardCode()}
); } @@ -138,7 +138,7 @@ class RewardsPage extends PureComponent { return (
diff --git a/src/ui/page/search/view.jsx b/src/ui/page/search/view.jsx index 07c68016c..45967d79d 100644 --- a/src/ui/page/search/view.jsx +++ b/src/ui/page/search/view.jsx @@ -2,8 +2,8 @@ import * as ICONS from 'constants/icons'; import React, { useEffect, Fragment } from 'react'; import { isURIValid, normalizeURI } from 'lbry-redux'; -import FileListItem from 'component/fileListItem'; -import FileList from 'component/fileList'; +import ClaimListItem from 'component/claimListItem'; +import ClaimList from 'component/claimList'; import Page from 'component/page'; import SearchOptions from 'component/searchOptions'; import Button from 'component/button'; @@ -49,12 +49,12 @@ export default function SearchPage(props: Props) { - +
)}
- } headerAltControls={ diff --git a/src/ui/page/sendCredits/index.js b/src/ui/page/sendCredits/index.js deleted file mode 100644 index 0d19a7d34..000000000 --- a/src/ui/page/sendCredits/index.js +++ /dev/null @@ -1,3 +0,0 @@ -import SendReceivePage from './view'; - -export default SendReceivePage; diff --git a/src/ui/page/sendCredits/view.jsx b/src/ui/page/sendCredits/view.jsx deleted file mode 100644 index 8e6017929..000000000 --- a/src/ui/page/sendCredits/view.jsx +++ /dev/null @@ -1,18 +0,0 @@ -import React from 'react'; -import classnames from 'classnames'; -import WalletSend from 'component/walletSend'; -import WalletAddress from 'component/walletAddress'; -import Page from 'component/page'; -import UnsupportedOnWeb from 'component/common/unsupported-on-web'; - -const SendReceivePage = () => ( - - {IS_WEB && } -
- - -
-
-); - -export default SendReceivePage; diff --git a/src/ui/page/subscriptions/index.js b/src/ui/page/subscriptions/index.js index b03752238..676b3626d 100644 --- a/src/ui/page/subscriptions/index.js +++ b/src/ui/page/subscriptions/index.js @@ -1,19 +1,19 @@ import { connect } from 'react-redux'; import { - selectSubscriptionClaims, selectSubscriptions, selectSubscriptionsBeingFetched, selectIsFetchingSubscriptions, selectSuggestedChannels, } from 'redux/selectors/subscriptions'; import { doFetchMySubscriptions, doFetchRecommendedSubscriptions } from 'redux/actions/subscriptions'; +import { selectLastClaimSearchUris, doClaimSearch } from 'lbry-redux'; import SubscriptionsPage from './view'; const select = state => ({ loading: selectIsFetchingSubscriptions(state) || Boolean(Object.keys(selectSubscriptionsBeingFetched(state)).length), subscribedChannels: selectSubscriptions(state), - subscriptionContent: selectSubscriptionClaims(state), suggestedSubscriptions: selectSuggestedChannels(state), + uris: selectLastClaimSearchUris(state), }); export default connect( @@ -21,5 +21,6 @@ export default connect( { doFetchMySubscriptions, doFetchRecommendedSubscriptions, + doClaimSearch, } )(SubscriptionsPage); diff --git a/src/ui/page/subscriptions/view.jsx b/src/ui/page/subscriptions/view.jsx index 2828e9d5b..28774a65d 100644 --- a/src/ui/page/subscriptions/view.jsx +++ b/src/ui/page/subscriptions/view.jsx @@ -1,53 +1,78 @@ // @flow -import React, { useEffect, useState } from 'react'; +import * as PAGES from 'constants/pages'; +import React, { useEffect } from 'react'; import Page from 'component/page'; -import FileList from 'component/fileList'; +import ClaimList from 'component/claimList'; import Button from 'component/button'; type Props = { - subscribedChannels: Array, // The channels a user is subscribed to - subscriptionContent: Array<{ uri: string, ...StreamClaim }>, + subscribedChannels: Array<{ uri: string }>, // The channels a user is subscribed to suggestedSubscriptions: Array<{ uri: string }>, loading: boolean, doFetchMySubscriptions: () => void, doFetchRecommendedSubscriptions: () => void, + location: { search: string }, + history: { push: string => void }, + doClaimSearch: (number, {}) => void, + uris: Array, }; export default function SubscriptionsPage(props: Props) { const { - subscriptionContent, subscribedChannels, doFetchMySubscriptions, doFetchRecommendedSubscriptions, suggestedSubscriptions, loading, + location, + history, + doClaimSearch, + uris, } = props; + const hasSubscriptions = !!subscribedChannels.length; - const [showSuggested, setShowSuggested] = useState(!hasSubscriptions); + const { search } = location; + const urlParams = new URLSearchParams(search); + const viewingSuggestedSubs = urlParams.get('view'); + + function onClick() { + let url = `/$/${PAGES.SUBSCRIPTIONS}`; + if (!viewingSuggestedSubs) { + url += '?view=discover'; + } + + history.push(url); + } useEffect(() => { doFetchMySubscriptions(); doFetchRecommendedSubscriptions(); }, [doFetchMySubscriptions, doFetchRecommendedSubscriptions]); + const idString = subscribedChannels.map(channel => channel.uri.split('#')[1]).join(','); + useEffect(() => { + const ids = idString.split(','); + const options = { + channel_ids: ids, + }; + + doClaimSearch(20, options); + }, [idString, doClaimSearch]); + return (
- {showSuggested ? __('Discover New Channels') : __('Latest From Your Subscriptions')}} + header={

{viewingSuggestedSubs ? __('Discover New Channels') : __('Latest From Your Subscriptions')}

} headerAltControls={
diff --git a/src/ui/page/tags/index.js b/src/ui/page/tags/index.js index dd4d22847..5bf5a2ec7 100644 --- a/src/ui/page/tags/index.js +++ b/src/ui/page/tags/index.js @@ -1,14 +1,14 @@ import { connect } from 'react-redux'; -import { selectFollowedTags } from 'lbry-redux'; +import { selectFollowedTags, doToggleTagFollow } from 'lbry-redux'; import Tags from './view'; const select = state => ({ followedTags: selectFollowedTags(state), }); -const perform = {}; - export default connect( select, - perform + { + doToggleTagFollow, + } )(Tags); diff --git a/src/ui/page/tags/view.jsx b/src/ui/page/tags/view.jsx index 931c1f485..e56be12bc 100644 --- a/src/ui/page/tags/view.jsx +++ b/src/ui/page/tags/view.jsx @@ -1,26 +1,43 @@ // @flow import React from 'react'; import Page from 'component/page'; -import FileListDiscover from 'component/fileListDiscover'; +import ClaimListDiscover from 'component/claimListDiscover'; +import Button from 'component/button'; type Props = { location: { search: string }, + followedTags: Array, + doToggleTagFollow: string => void, }; function TagsPage(props: Props) { const { location: { search }, + followedTags, + doToggleTagFollow, } = props; const urlParams = new URLSearchParams(search); const tagsQuery = urlParams.get('t') || ''; const tags = tagsQuery.split(','); + // Eventually allow more than one tag on this page + // Restricting to one to make follow/unfollow simpler + const tag = tags[0]; + + const isFollowing = followedTags.map(({ name }) => name).includes(tag); return ( -
- -
+ doToggleTagFollow(tag)} + label={isFollowing ? __('Unfollow this tag') : __('Follow this tag')} + /> + } + />
); } diff --git a/src/ui/page/transactionHistory/index.js b/src/ui/page/transactionHistory/index.js index 92006a6c5..9a8d2b1fb 100644 --- a/src/ui/page/transactionHistory/index.js +++ b/src/ui/page/transactionHistory/index.js @@ -1,14 +1,8 @@ import { connect } from 'react-redux'; -import { - doFetchTransactions, - selectTransactionItems, - selectIsFetchingTransactions, - doFetchClaimListMine, -} from 'lbry-redux'; +import { doFetchTransactions, selectTransactionItems, doFetchClaimListMine } from 'lbry-redux'; import TransactionHistoryPage from './view'; const select = state => ({ - fetchingTransactions: selectIsFetchingTransactions(state), transactions: selectTransactionItems(state), }); diff --git a/src/ui/page/transactionHistory/view.jsx b/src/ui/page/transactionHistory/view.jsx index 712646afe..5dfec660a 100644 --- a/src/ui/page/transactionHistory/view.jsx +++ b/src/ui/page/transactionHistory/view.jsx @@ -1,10 +1,8 @@ // @flow import React from 'react'; import classnames from 'classnames'; -import BusyIndicator from 'component/common/busy-indicator'; import TransactionList from 'component/transactionList'; import Page from 'component/page'; -import RefreshTransactionButton from 'component/transactionRefreshButton'; import UnsupportedOnWeb from 'component/common/unsupported-on-web'; type Props = { @@ -23,36 +21,17 @@ class TransactionHistoryPage extends React.PureComponent { } render() { - const { fetchingTransactions, transactions } = this.props; + const { transactions } = this.props; return ( {IS_WEB && }
-
-

- {__('Transaction History')} - -

-
- {fetchingTransactions && !transactions.length ? ( -
- -
- ) : ( - '' - )} - {transactions && transactions.length ? ( -
- -
- ) : ( -
{__("Looks like you don't have any transactions")}
- )} +
); diff --git a/src/ui/page/userHistory/view.jsx b/src/ui/page/userHistory/view.jsx index 61b92fefd..bdf85c340 100644 --- a/src/ui/page/userHistory/view.jsx +++ b/src/ui/page/userHistory/view.jsx @@ -1,7 +1,6 @@ // @flow import React from 'react'; import Page from 'component/page'; -import UserHistory from 'component/navigationHistoryRecent'; import DownloadList from 'page/fileListDownloaded'; type Props = {}; @@ -10,7 +9,6 @@ class UserHistoryPage extends React.PureComponent { render() { return ( - ); diff --git a/src/ui/component/fileList/index.js b/src/ui/page/wallet/index.js similarity index 77% rename from src/ui/component/fileList/index.js rename to src/ui/page/wallet/index.js index f73f0fcd6..6d797c4ab 100644 --- a/src/ui/component/fileList/index.js +++ b/src/ui/page/wallet/index.js @@ -1,5 +1,5 @@ import { connect } from 'react-redux'; -import FileList from './view'; +import Wallet from './view'; const select = state => ({}); @@ -8,4 +8,4 @@ const perform = dispatch => ({}); export default connect( select, perform -)(FileList); +)(Wallet); diff --git a/src/ui/page/wallet/view.jsx b/src/ui/page/wallet/view.jsx new file mode 100644 index 000000000..c93b3a2c9 --- /dev/null +++ b/src/ui/page/wallet/view.jsx @@ -0,0 +1,17 @@ +import React from 'react'; +import WalletBalance from 'component/walletBalance'; +import WalletSend from 'component/walletSend'; +import WalletAddress from 'component/walletAddress'; +import TransactionListRecent from 'component/transactionListRecent'; +import Page from 'component/page'; + +const WalletPage = () => ( + + + + + + +); + +export default WalletPage; diff --git a/src/ui/reducers.js b/src/ui/reducers.js index c9641f3a3..bb89aa2c5 100644 --- a/src/ui/reducers.js +++ b/src/ui/reducers.js @@ -6,7 +6,7 @@ import { searchReducer, walletReducer, notificationsReducer, - tagsReducer, + tagsReducerBuilder, } from 'lbry-redux'; import { userReducer, rewardsReducer, costInfoReducer, blacklistReducer, homepageReducer, statsReducer } from 'lbryinc'; import appReducer from 'redux/reducers/app'; @@ -15,6 +15,17 @@ import contentReducer from 'redux/reducers/content'; import settingsReducer from 'redux/reducers/settings'; import subscriptionsReducer from 'redux/reducers/subscriptions'; import publishReducer from 'redux/reducers/publish'; +import { defaultKnownTags, defaultFollowedTags } from 'constants/tags'; + +function getDefaultKnownTags() { + return defaultFollowedTags.concat(defaultKnownTags).reduce( + (tagsMap, tag) => ({ + ...tagsMap, + [tag]: { name: tag }, + }), + {} + ); +} export default history => combineReducers({ @@ -34,7 +45,7 @@ export default history => settings: settingsReducer, stats: statsReducer, subscriptions: subscriptionsReducer, - tags: tagsReducer, + tags: tagsReducerBuilder({ followedTags: defaultFollowedTags, knownTags: getDefaultKnownTags() }), user: userReducer, wallet: walletReducer, }); diff --git a/src/ui/redux/selectors/subscriptions.js b/src/ui/redux/selectors/subscriptions.js index c1152c667..e4fb71b31 100644 --- a/src/ui/redux/selectors/subscriptions.js +++ b/src/ui/redux/selectors/subscriptions.js @@ -16,7 +16,7 @@ const selectState = state => state.subscriptions || {}; // Returns the list of channel uris a user is subscribed to export const selectSubscriptions = createSelector( selectState, - state => state.subscriptions + state => state.subscriptions && state.subscriptions.sort((a, b) => a.channelName.localeCompare(b.channelName)) ); // Fetching list of users subscriptions diff --git a/src/ui/scss/all.scss b/src/ui/scss/all.scss index 404f8dcf2..b14ebd8d8 100644 --- a/src/ui/scss/all.scss +++ b/src/ui/scss/all.scss @@ -23,12 +23,12 @@ @import 'component/file-render'; @import 'component/form-field'; @import 'component/header'; -@import 'component/icon'; @import 'component/item-list'; @import 'component/main'; @import 'component/markdown-editor'; @import 'component/markdown-preview'; @import 'component/media'; +@import 'component/menu-button'; @import 'component/modal'; @import 'component/navigation'; @import 'component/notice'; diff --git a/src/ui/scss/component/_badge.scss b/src/ui/scss/component/_badge.scss index 0435f5645..874ee2822 100644 --- a/src/ui/scss/component/_badge.scss +++ b/src/ui/scss/component/_badge.scss @@ -4,6 +4,9 @@ @extend .badge; background-color: lighten($lbry-teal-5, 55%); color: darken($lbry-teal-5, 20%); + svg { + stroke: $lbry-teal-5; + } [data-mode='dark'] & { color: lighten($lbry-teal-5, 60%); diff --git a/src/ui/scss/component/_button.scss b/src/ui/scss/component/_button.scss index 1c2cc57b8..99fc00438 100644 --- a/src/ui/scss/component/_button.scss +++ b/src/ui/scss/component/_button.scss @@ -2,6 +2,7 @@ .button { display: inline-block; + font-weight: 400; svg { stroke-width: 1.9; @@ -17,7 +18,9 @@ } } -.button--primary { +// Fix this in lbry/components +.button--primary:not(:hover) { + background-color: $lbry-teal-4; svg { color: white; } @@ -28,10 +31,12 @@ height: 5rem; width: 5rem; border-radius: 2.5rem; + &:not(:hover) { + background-color: $lbry-teal-4; + } } .button--primary, -.button--alt, .button--inverse { height: var(--button-height); line-height: var(--button-height); @@ -42,6 +47,18 @@ box-sizing: border-box; } +.button--inverse { + border-color: $lbry-teal-4; + + &:hover { + color: $lbry-white; + background-color: $lbry-teal-4; + .icon { + stroke: $lbry-white; + } + } +} + .button--alt { padding: 0; } @@ -67,7 +84,7 @@ transition: all var(--transition-duration) var(--transition-style); &:hover { - background-color: $lbry-red-3; + background-color: $lbry-black; color: $lbry-white; border-radius: var(--card-radius); } @@ -78,12 +95,16 @@ align-items: flex-start; } +.button__content { + display: flex; + align-items: center; + min-width: 0; +} + .button__label { - // white-space: nowrap; + white-space: nowrap; overflow: hidden; text-overflow: ellipsis; - // display: flex; - // align-items: center; } // Handle icons on the left or right side of the button label @@ -91,8 +112,3 @@ svg + .button__label, .button__label + svg { margin-left: var(--spacing-miniscule); } - -.button__content { - display: flex; - align-items: center; -} diff --git a/src/ui/scss/component/_card.scss b/src/ui/scss/component/_card.scss index c423f30f7..65b523b87 100644 --- a/src/ui/scss/component/_card.scss +++ b/src/ui/scss/component/_card.scss @@ -1,10 +1,11 @@ .card { background-color: $lbry-white; - margin-bottom: var(--spacing-xlarge); + margin-bottom: var(--spacing-large); position: relative; border-radius: var(--card-radius); box-shadow: var(--card-box-shadow) $lbry-gray-1; overflow: hidden; + font-size: 1.25rem; html[data-mode='dark'] & { background-color: lighten($lbry-black, 5%); @@ -41,6 +42,13 @@ justify-content: space-between; } +.card--reward-total { + background-repeat: no-repeat; + background-size: cover; + // justify-content: space-between; + color: $lbry-white; +} + .card--modal { box-shadow: none; } @@ -50,6 +58,7 @@ .card__actions { display: flex; + align-items: center; font-size: 1.15rem; > *:not(:last-child) { @@ -83,19 +92,23 @@ padding-top: var(--spacing-small); } +.card__actions--table { + padding: var(--spacing-medium); +} + // C A R D // C O N T E N T .card__content { - font-size: 1.25rem; - p:not(:last-child) { margin-bottom: var(--spacing-medium); } } .card__content--large { - font-size: 4rem; + font-size: 3rem; + line-height: 1.5; + font-weight: 700; } // C A R D @@ -113,41 +126,13 @@ // L I S T .card__list { - display: grid; - grid-gap: var(--spacing-medium); - margin-top: var(--spacing-large); - - // Depending on screen width, the amount of items in - // each row change and are auto-sized - - // @media (min-width: 2001px) { - // grid-template-columns: repeat(auto-fill, minmax(calc(100% / 10), 1fr)); - // } - - // @media (min-width: 1801px) and (max-width: 2000px) { - // grid-template-columns: repeat(auto-fill, minmax(calc(100% / 8), 1fr)); - // } - - @media (min-width: 1551px) { - grid-template-columns: repeat(auto-fill, minmax(calc(100% / 7), 1fr)); - } - - @media (min-width: 1200px) and (max-width: 1550px) { - grid-template-columns: repeat(auto-fill, minmax(calc(100% / 6), 1fr)); - } - - grid-template-columns: repeat(auto-fill, minmax(calc(100% / 5), 1fr)); -} - -.card__list--rewards { column-count: 2; column-gap: var(--spacing-medium); - margin-bottom: var(--spacing-large); + display: block; .card { display: inline-block; margin: 0 0 var(--spacing-medium); - width: 100%; } } @@ -185,6 +170,7 @@ .card__subtitle { @extend .help; color: darken($lbry-gray-5, 25%); + background-color: lighten($lbry-gray-1, 5%); font-size: 1.15rem; margin-bottom: var(--spacing-small); flex: 1; @@ -200,8 +186,7 @@ } [data-mode='dark'] & { - // TODO: dark - // background-color: darken($lbry-gray-5, 20%); + background-color: darken($lbry-gray-5, 20%); } } diff --git a/src/ui/scss/component/_content.scss b/src/ui/scss/component/_content.scss index 470fde947..c98657cf4 100644 --- a/src/ui/scss/component/_content.scss +++ b/src/ui/scss/component/_content.scss @@ -23,7 +23,7 @@ .button--view, .button--play { - background-color: $lbry-green-3; + background-color: $lbry-teal-2; } } } @@ -104,6 +104,7 @@ } .content__view--container { + background-color: black; width: 100%; height: 100%; top: 0; diff --git a/src/ui/scss/component/_file-list.scss b/src/ui/scss/component/_file-list.scss index 01687aabd..ded90bb46 100644 --- a/src/ui/scss/component/_file-list.scss +++ b/src/ui/scss/component/_file-list.scss @@ -1,8 +1,9 @@ .file-list__header { display: flex; align-items: center; - min-height: 4rem; + height: 4.5rem; padding: var(--spacing-medium); + font-size: 1rem; // Ensures select & header text have same font-size color: $lbry-white; border-top-left-radius: var(--card-radius); border-top-right-radius: var(--card-radius); @@ -14,6 +15,20 @@ fieldset-section { margin-bottom: 0; } + + // Normal link buttons are too dark on the black file list background + .button--link { + color: $lbry-teal-3; + + &:hover { + color: $lbry-teal-1; + } + } +} + +.file-list__header--small { + height: 3rem; + font-size: 1em; } .file-list__dropdown { @@ -53,6 +68,7 @@ display: flex; align-items: center; margin-left: auto; + font-size: 1.4em; & > * { margin-left: var(--spacing-small); @@ -80,10 +96,6 @@ flex-shrink: 0; margin-right: var(--spacing-medium); } - - .media__thumb--profile { - width: 6rem; - } } .file-list__item--injected, @@ -135,3 +147,8 @@ .file-list__item-tags { margin-left: 0; } + +.file-list__meta { + padding: var(--spacing-medium); + background-color: lighten($lbry-teal-5, 55%); +} diff --git a/src/ui/scss/component/_file-properties.scss b/src/ui/scss/component/_file-properties.scss index 49142fb89..c1821ff89 100644 --- a/src/ui/scss/component/_file-properties.scss +++ b/src/ui/scss/component/_file-properties.scss @@ -3,11 +3,21 @@ position: relative; align-items: center; - & > *:not(:first-child) { - margin-left: var(--spacing-small); + & > *:not(:last-child) { + margin-right: var(--spacing-small); } @media (max-width: 600px) { display: none; } } + +.file-properties--large { + flex-wrap: wrap; + font-size: 18px; + margin: var(--spacing-small) 0; + + & > * { + margin-top: var(--spacing-small); + } +} diff --git a/src/ui/scss/component/_form-field.scss b/src/ui/scss/component/_form-field.scss index 02006ff25..9d4c38db5 100644 --- a/src/ui/scss/component/_form-field.scss +++ b/src/ui/scss/component/_form-field.scss @@ -176,15 +176,15 @@ fieldset-group { form { [type='button'], [type='submit'] { - &.button--primary { + &.button--inverse { &:not(:hover) { - background-color: $lbry-teal-5; - border-color: $lbry-teal-5; + background-color: transparent; + border-color: $lbry-black; + color: $lbry-black; } &:hover { - background-color: $lbry-teal-3; - border-color: $lbry-teal-3; + background-color: $lbry-teal-4; } } } @@ -203,6 +203,7 @@ fieldset-section { // input-submit is connected to a button // The input height needs to match the button height to lineup correctly // Other inputs are fine since they are on their own and are used under different circumstances + input[type='email'], input[type='text'] { height: var(--button-height); @@ -218,6 +219,7 @@ fieldset-section { border-bottom-left-radius: 0; border-top-right-radius: var(--input-border-radius); border-bottom-right-radius: var(--input-border-radius); + border-color: $lbry-black; } } diff --git a/src/ui/scss/component/_header.scss b/src/ui/scss/component/_header.scss index 6eddd693f..7e6472b3b 100644 --- a/src/ui/scss/component/_header.scss +++ b/src/ui/scss/component/_header.scss @@ -5,11 +5,14 @@ width: 100%; background-color: $lbry-white; border-bottom: 1px solid $lbry-gray-1; - + box-shadow: var(--card-box-shadow) $lbry-gray-1; + padding-left: var(--spacing-large); + padding-right: var(--spacing-large); html[data-mode='dark'] & { background-color: mix($lbry-black, $lbry-gray-3, 90%); color: $lbry-white; border-bottom: none; + box-shadow: var(--card-box-shadow) $lbry-black; } } @@ -17,7 +20,6 @@ width: 100%; height: calc(var(--header-height) - 1px); max-width: var(--page-max-width); - padding-left: var(--spacing-medium); display: flex; justify-content: space-between; margin: auto; @@ -25,14 +27,13 @@ .header__navigation { display: flex; + justify-content: space-between; &:last-of-type { - padding-left: var(--spacing-small); - width: var(--side-nav-width); - } - - @media (max-width: 600px) { - display: none; + width: calc(var(--side-nav-width) + var(--spacing-medium)); + @media (max-width: 600px) { + display: none; + } } } @@ -49,7 +50,7 @@ border-radius: 0; svg { - stroke: $lbry-black; + stroke: $lbry-gray-5; } &:hover { @@ -109,28 +110,15 @@ } .header__navigation-item--right-action { - &:first-of-type { - margin-right: auto; - } - - &:not(:first-of-type) { - padding: 0 var(--spacing-medium); - } - - &:last-of-type { - margin-right: 0; - } + align-self: flex-end; + margin-left: auto; + padding: 0 var(--spacing-small); } .header__navigation-item--upgrade { - background-color: $lbry-teal-5; - color: $lbry-white; + color: $lbry-teal-5; svg { - stroke: $lbry-white; - } - - &:hover { - background-color: $lbry-teal-4; + stroke: $lbry-teal-5; } } diff --git a/src/ui/scss/component/_icon.scss b/src/ui/scss/component/_icon.scss deleted file mode 100644 index 74bd2c7d0..000000000 --- a/src/ui/scss/component/_icon.scss +++ /dev/null @@ -1,11 +0,0 @@ -// Not all icons are created equally... at least the react-feather ones aren't -// Minor adjustments to ensure icons line up vertically - -.icon--Flag, -.icon--Home { - top: -2px; -} - -.icon--Heart { - top: -1px; -} diff --git a/src/ui/scss/component/_main.scss b/src/ui/scss/component/_main.scss index 0c91d2726..89d5c205d 100644 --- a/src/ui/scss/component/_main.scss +++ b/src/ui/scss/component/_main.scss @@ -2,8 +2,9 @@ position: absolute; min-height: 100vh; width: 100vw; - padding-top: var(--spacing-main-padding); - padding-left: var(--spacing-medium); + padding-top: var(--header-height); + padding-left: var(--spacing-large); + padding-right: var(--spacing-large); background-color: mix($lbry-white, $lbry-gray-1, 70%); display: flex; @@ -18,7 +19,7 @@ width: 100%; margin-left: auto; margin-right: auto; - margin-top: var(--spacing-main-padding); + margin-top: var(--spacing-large); position: relative; } @@ -36,7 +37,6 @@ .main--file-page { display: grid; - grid-gap: var(--spacing-large); grid-template-rows: auto 1fr; grid-template-columns: 1fr auto; max-width: calc(100% - var(--side-nav-width) - var(--spacing-main-padding)); @@ -57,7 +57,20 @@ } .grid-area--related { grid-area: related; - width: 40rem; + min-width: 30rem; + max-width: 35rem; + } + + @media (max-width: 600px) { + grid-template-areas: + 'content' + 'info' + 'related'; + + .grid-area--related { + grid-area: related; + width: auto; + } } } @@ -69,3 +82,15 @@ padding-bottom: 100px; text-align: center; } + +.main__status { + @extend .help; + display: flex; + justify-content: space-between; + background-color: $lbry-teal-4; + color: $lbry-white; + + svg { + stroke: $lbry-white; + } +} diff --git a/src/ui/scss/component/_markdown-preview.scss b/src/ui/scss/component/_markdown-preview.scss index 9d6dc1553..324e00af9 100644 --- a/src/ui/scss/component/_markdown-preview.scss +++ b/src/ui/scss/component/_markdown-preview.scss @@ -85,9 +85,13 @@ font-family: Consolas, 'Lucida Console', 'Source Sans', monospace; } - a { - color: $lbry-blue-1; + a, + button { display: inline-block; + + .button__label { + white-space: normal; + } } // Lists diff --git a/src/ui/scss/component/_media.scss b/src/ui/scss/component/_media.scss index b00389e8a..32b310665 100644 --- a/src/ui/scss/component/_media.scss +++ b/src/ui/scss/component/_media.scss @@ -45,13 +45,6 @@ background-image: linear-gradient(to bottom right, $lbry-teal-3, $lbry-grape-5 100%); } -.media__thumb--profile { - // height: var(--channel-thumbnail-width); - width: 70px; - height: 70px; - background-size: cover; -} - // M E D I A // T I T L E @@ -69,16 +62,16 @@ margin-right: var(--spacing-small); } +.media__uri-wrapper { + display: flex; + justify-content: space-between; + margin-bottom: var(--spacing-small); +} + .media__uri { font-size: 1.1rem; - padding-bottom: 5px; - opacity: 0.6; - user-select: all; - height: 2rem; - // position: absolute; - // top: 2rem; - // transform: translateY(-2rem); - // margin-bottom: -50px; + min-width: 0; + margin-right: var(--spacing-small); } .media__insufficient-credits { @@ -107,7 +100,6 @@ .media__action-group--large { display: flex; - align-items: flex-end; margin-top: var(--spacing-small); margin-bottom: var(--spacing-small); @@ -190,7 +182,7 @@ .media__info--large { border-top: 1px solid $lbry-gray-1; - padding-top: var(--spacing-medium); + margin-top: var(--spacing-medium); html[data-mode='dark'] & { border-color: rgba($lbry-gray-5, 0.2); @@ -212,6 +204,11 @@ &.media__info-text--center { text-align: center; } + + .button__label { + text-align: left; + white-space: normal; + } } .media__info-title { diff --git a/src/ui/scss/component/_navigation.scss b/src/ui/scss/component/_navigation.scss index 2335fa27e..10f8928f6 100644 --- a/src/ui/scss/component/_navigation.scss +++ b/src/ui/scss/component/_navigation.scss @@ -6,7 +6,6 @@ } .navigation { - position: fixed; width: var(--side-nav-width); font-size: 1.4rem; @@ -22,11 +21,11 @@ .navigation__links--small { @extend .navigation__links; font-size: 1.2rem; + margin-top: var(--spacing-small); } .navigation__link { display: block; - line-height: 1.75; position: relative; text-align: left; transition: color 0.2s; @@ -34,6 +33,11 @@ white-space: nowrap; text-overflow: ellipsis; color: lighten($lbry-black, 20%); + margin-top: var(--spacing-miniscule); + + .icon { + margin-right: var(--spacing-small); + } &:hover { color: $lbry-teal-4; @@ -112,3 +116,7 @@ } } } + +.navigation__link--indented { + padding-left: 2rem; +} diff --git a/src/ui/scss/component/_spinner.scss b/src/ui/scss/component/_spinner.scss index 66717e333..38c2405d8 100644 --- a/src/ui/scss/component/_spinner.scss +++ b/src/ui/scss/component/_spinner.scss @@ -46,6 +46,7 @@ .spinner--small { height: 10px; + display: inline-block; .rect { width: 3px; diff --git a/src/ui/scss/component/_table.scss b/src/ui/scss/component/_table.scss index f822edadb..df0dbab62 100644 --- a/src/ui/scss/component/_table.scss +++ b/src/ui/scss/component/_table.scss @@ -2,6 +2,8 @@ table, .table { + margin-bottom: var(--spacing-small); + [data-mode='dark'] & { background-color: transparent; @@ -9,17 +11,23 @@ table, border-bottom: 2px solid $lbry-white; } } + + th, + td { + padding-left: var(--spacing-large); + } } td { - max-width: 0; overflow: hidden; - text-overflow: ellipsis; - white-space: nowrap; } -tr { - padding: 0 var(--spacing-small); +.table__header { + margin: var(--spacing-large); + + & + .table__header { + margin-top: 0; + } } .table__item--actionable { @@ -45,6 +53,17 @@ tr { .table--transactions { table-layout: fixed; + + td:nth-of-type(3) { + // Only add ellipsis to the links in the table + // We still want to show the entire message if a TX includes one + a, + button { + @include constrict(10rem); + vertical-align: bottom; + display: inline-block; + } + } } .table--rewards { diff --git a/src/ui/scss/component/_tags.scss b/src/ui/scss/component/_tags.scss index 23c9cc817..91e04d49d 100644 --- a/src/ui/scss/component/_tags.scss +++ b/src/ui/scss/component/_tags.scss @@ -11,15 +11,6 @@ $main: $lbry-teal-5; } } -.tags, -.tags--remove, -.tags--add { - .button__label { - display: flex; - align-items: center; - } -} - .tags--remove { @extend .tags; margin-bottom: var(--spacing-large); @@ -53,40 +44,34 @@ $main: $lbry-teal-5; text-transform: lowercase; font-size: 0.7em; max-width: 10rem; + min-width: 0; - &:hover:not(:disabled) { - background-color: $main; + &:hover { + background-color: $lbry-teal-4; color: $lbry-white; + svg { + stroke: $lbry-white; + } } - &:active, - &:focus { + &:active { background-color: $main; } } .tag--remove { @extend .tag; - font-size: 1em !important; max-width: 20rem; } .tag--add { - @extend .tag; - background-color: rgba($main, 0.05); - border: 1px solid rgba($main, 0.3); - border-radius: 1rem; - transition: all var(--animation-duration) var(--animation-style); - - &:hover { - border-radius: 3px; - } + background-color: lighten($lbry-teal-5, 60%); } .tag__action-label { - border-left: 1px solid rgba($lbry-black, 0.1); margin-left: 0.5rem; padding-left: 0.5rem; + padding-top: 0.7rem; html[data-mode='dark'] & { border-color: rgba($lbry-white, 0.1); diff --git a/src/ui/scss/component/_wunderbar.scss b/src/ui/scss/component/_wunderbar.scss index 4f4a2a289..f58e10173 100644 --- a/src/ui/scss/component/_wunderbar.scss +++ b/src/ui/scss/component/_wunderbar.scss @@ -7,7 +7,7 @@ flex: 1; position: relative; z-index: 1; - margin-right: var(--spacing-xlarge); + margin-right: calc(var(--spacing-large)); @media (max-width: 600px) { margin-right: 0; @@ -39,8 +39,12 @@ background-color: $lbry-gray-1; align-items: center; border: none; - display: flex; - justify-content: center; + min-width: 0; + padding-right: var(--spacing-small); + overflow: hidden; + text-overflow: ellipsis; + white-space: nowrap; + padding-left: 2.5rem; transition: all 0.2s; diff --git a/src/ui/scss/component/menu-button.scss b/src/ui/scss/component/menu-button.scss new file mode 100644 index 000000000..f3613f74a --- /dev/null +++ b/src/ui/scss/component/menu-button.scss @@ -0,0 +1,97 @@ +// Extends reach-ui menu button base stylesheet +/* Used to detect in JavaScript if apps have loaded styles or not. */ +:root { + --reach-menu-button: 1; +} + +[data-reach-menu] { + font-family: sans-serif; + display: block; + position: absolute; +} + +[data-reach-menu-list] { + display: block; + white-space: nowrap; + outline: none; + font-size: 1.2rem; + background-color: $lbry-white; + box-shadow: 0px 10px 30px 2px $lbry-gray-2; + border: 1px solid $lbry-gray-1; + border-top: none; + + [data-mode='dark'] & { + background-color: lighten($lbry-black, 10%); + color: $lbry-white; + box-shadow: 0 10px 30px 2px $lbry-black; + border: 1px solid $lbry-gray-5; + border-top: none; + } +} + +[data-reach-menu-item] { + display: block; +} + +[data-reach-menu-item] { + cursor: pointer; + display: block; + color: inherit; + font: inherit; + text-decoration: initial; +} + +[data-reach-menu-item][data-selected] { + background: lighten($lbry-teal-5, 55%); + color: darken($lbry-teal-5, 15%); + outline: none; + + &:active { + background-color: $lbry-teal-4; + color: $lbry-white; + .icon { + stroke: $lbry-white; + } + } + + [data-mode='dark'] & { + background-color: $lbry-teal-5; + color: $lbry-white; + + &:hover, + &:focus { + .icon { + stroke: $lbry-white; + } + } + } +} + +.menu__title { + padding: var(--spacing-large) 0; + padding-left: var(--spacing-medium); + padding-right: 0; + + span { + margin-left: var(--spacing-small); + } +} + +.menu__link { + display: flex; + align-items: center; + padding: var(--spacing-medium); +} + +.menu__title, +.menu__link { + font-size: 1.3rem; + color: lighten($lbry-black, 20%); + + .icon { + margin-right: var(--spacing-small); + margin-bottom: 0.2rem; + + stroke: $lbry-gray-5; + } +} diff --git a/src/ui/scss/init/_gui.scss b/src/ui/scss/init/_gui.scss index 2d7638d16..9e55bd7ac 100644 --- a/src/ui/scss/init/_gui.scss +++ b/src/ui/scss/init/_gui.scss @@ -54,10 +54,10 @@ code { justify-content: space-between; > * { - flex-basis: 0; flex-grow: 1; + flex-basis: 0; - &:not(:last-of-type) { + &:first-child { margin-right: 1.5rem; } } @@ -130,7 +130,7 @@ code { .help { font-size: 1rem; background-color: rgba($lbry-blue-1, 0.1); - color: $lbry-gray-5; + color: darken($lbry-gray-5, 15%); display: block; padding: 1rem; margin-top: var(--spacing-medium); diff --git a/src/ui/scss/init/_vars.scss b/src/ui/scss/init/_vars.scss index eff778e53..bc7fb44aa 100644 --- a/src/ui/scss/init/_vars.scss +++ b/src/ui/scss/init/_vars.scss @@ -46,7 +46,7 @@ $large-breakpoint: 1921px; --button-height: 2.6rem; // Header - --header-height: 5rem; + --header-height: 6rem; // Card --card-radius: 5px; diff --git a/src/ui/util/format-credits.js b/src/ui/util/format-credits.js index 339ea3c42..0f36c8b82 100644 --- a/src/ui/util/format-credits.js +++ b/src/ui/util/format-credits.js @@ -5,8 +5,11 @@ export function formatCredits(amount, precision = 1) { } export function formatFullPrice(amount, precision = 1) { - let formated = ''; + if (!amount) { + return 0; + } + let formated = ''; const quantity = amount.toString().split('.'); const fraction = quantity[1]; diff --git a/src/ui/util/use-tween.js b/src/ui/util/use-tween.js new file mode 100644 index 000000000..724db2f03 --- /dev/null +++ b/src/ui/util/use-tween.js @@ -0,0 +1,31 @@ +import { useEffect, useState } from 'react'; + +const getProgress = (elapsed, duration) => Math.min(elapsed / duration, 1); +const easeOut = progress => Math.pow(progress - 1, 5) + 1; + +export default function useTween(duration, onRest) { + const [value, setValue] = useState(0); + + useEffect(() => { + let start = performance.now(); + let elapsed = 0; + let frame; + + const tick = now => { + elapsed = now - start; + const progress = getProgress(elapsed, duration); + setValue(easeOut(progress)); + if (progress < 1) { + frame = requestAnimationFrame(tick); + } else { + onRest && onRest(); + } + }; + + frame = requestAnimationFrame(tick); + + return () => cancelAnimationFrame(frame); + }, [duration, onRest]); + + return value; +} diff --git a/static/locales/en.json b/static/locales/en.json index d00f01883..48e468eef 100644 --- a/static/locales/en.json +++ b/static/locales/en.json @@ -4,80 +4,192 @@ "Cancel": "Cancel", "Show More...": "Show More...", "Show Less": "Show Less", - "Starting up": "Starting up", - "Connecting": "Connecting", "LBRY": "LBRY", "Navigate back": "Navigate back", "Navigate forward": "Navigate forward", - "Menu": "Menu", - "Your wallet": "Your wallet", - "Publish content": "Publish content", + "Account": "Account", + "Overview": "Overview", + "Wallet": "Wallet", "Publish": "Publish", - "Discover": "Discover", + "Settings": "Settings", + "Help": "Help", + "Make This Your Own": "Make This Your Own", + "For": "For", + "No results": "No results", + "Home": "Home", "Subscriptions": "Subscriptions", "Publishes": "Publishes", "Library": "Library", - "Overview": "Overview", - "Invite": "Invite", - "Rewards": "Rewards", - "Send & Recieve": "Send & Recieve", - "Transactions": "Transactions", - "Settings": "Settings", - "Help": "Help", - "Failed to load landing content.": "Failed to load landing content.", - "Hi There": "Hi There", - "Using LBRY is like dating a centaur. Totally normal up top, and": "Using LBRY is like dating a centaur. Totally normal up top, and", - "way different": "way different", - "underneath.": "underneath.", - "Up top, LBRY is similar to popular media sites.": "Up top, LBRY is similar to popular media sites.", - "Below, LBRY is controlled by users -- you -- via blockchain and decentralization.": "Below, LBRY is controlled by users -- you -- via blockchain and decentralization.", - "I'm In": "I'm In", - "You Are Awesome!": "You Are Awesome!", - "Check out some of the neat content below me. I'll see you around!": "Check out some of the neat content below me. I'll see you around!", - "Lets Get Started": "Lets Get Started", - "Not Now": "Not Now", + "Following": "Following", + "The tags you follow will change what's trending for you.": "The tags you follow will change what's trending for you.", + "Tags": "Tags", + "Search for more tags": "Search for more tags", + "Publish content": "Publish content", + "Unfollow this tag": "Unfollow this tag", + "Follow this tag": "Follow this tag", + "Published on": "Published on", + "Send a tip": "Send a tip", + "Share": "Share", + "Play": "Play", "Subscribe": "Subscribe", - "Unsubscribe": "Unsubscribe", + "Report content": "Report content", + "Content-Type": "Content-Type", + "Languages": "Languages", + "License": "License", + "Want to comment?": "Want to comment?", + "More": "More", + "FREE": "FREE", + "Related": "Related", + "No related content found": "No related content found", + "Download": "Download", + "Content": "Content", + "What are you publishing?": "What are you publishing?", + "Read our": "Read our", + "FAQ": "FAQ", + "to learn more.": "to learn more.", + "Title": "Title", + "Titular Title": "Titular Title", + "Description": "Description", + "Description of your content": "Description of your content", + "Thumbnail": "Thumbnail", + "Upload your thumbnail (.png/.jpg/.jpeg/.gif) to": "Upload your thumbnail (.png/.jpg/.jpeg/.gif) to", + "spee.ch": "spee.ch", + "Recommended size: 800x450 (16:9)": "Recommended size: 800x450 (16:9)", + "Price": "Price", + "How much will this content cost?": "How much will this content cost?", + "Free": "Free", + "Choose price": "Choose price", + "Anonymous or under a channel?": "Anonymous or under a channel?", + "This is a username or handle that your content can be found under.": "This is a username or handle that your content can be found under.", + "Ex. @Marvel, @TheBeatles, @BooksByJoe": "Ex. @Marvel, @TheBeatles, @BooksByJoe", + "Where can people find this content?": "Where can people find this content?", + "The LBRY URL is the exact address where people find your content (ex. lbry://myvideo).": "The LBRY URL is the exact address where people find your content (ex. lbry://myvideo).", + "Learn more": "Learn more", + "Name": "Name", + "Deposit (LBC)": "Deposit (LBC)", + "Mature audiences only": "Mature audiences only", + "Language": "Language", + "English": "English", + "Chinese": "Chinese", + "French": "French", + "German": "German", + "Japanese": "Japanese", + "Russian": "Russian", + "Spanish": "Spanish", + "Indonesian": "Indonesian", + "Italian": "Italian", + "Dutch": "Dutch", + "Turkish": "Turkish", + "Polish": "Polish", + "Malay": "Malay", + "By continuing, you accept the": "By continuing, you accept the", + "LBRY Terms of Service": "LBRY Terms of Service", + "Choose File": "Choose File", + "No File Chosen": "No File Chosen", + "Choose Thumbnail": "Choose Thumbnail", + "Enter a thumbnail URL": "Enter a thumbnail URL", + "Anonymous": "Anonymous", + "New channel...": "New channel...", + "You already have a claim at": "You already have a claim at", + "Publishing will update your existing claim.": "Publishing will update your existing claim.", + "Any amount will give you the winning bid.": "Any amount will give you the winning bid.", + "This LBC remains yours and the deposit can be undone at any time.": "This LBC remains yours and the deposit can be undone at any time.", + "License (Optional)": "License (Optional)", + "None": "None", + "Public Domain": "Public Domain", + "Copyrighted...": "Copyrighted...", + "Other...": "Other...", + "Email": "Email", + "Your email has been successfully verified": "Your email has been successfully verified", + "Your Email": "Your Email", + "Change": "Change", + "This information is disclosed only to LBRY, Inc. and not to the LBRY network. It is only required to earn LBRY rewards.": "This information is disclosed only to LBRY, Inc. and not to the LBRY network. It is only required to earn LBRY rewards.", + "Rewards": "Rewards", + "You have": "You have", + "in unclaimed rewards": "in unclaimed rewards", + "Claim Rewards": "Claim Rewards", + "LBC": "LBC", + "Earned From Rewards": "Earned From Rewards", "Invite a Friend": "Invite a Friend", "When your friends start using LBRY, the network gets stronger!": "When your friends start using LBRY, the network gets stronger!", "Or share this link with your friends": "Or share this link with your friends", "Earn": "Earn", "rewards": "rewards", "for inviting your friends.": "for inviting your friends.", - "Read our": "Read our", - "FAQ": "FAQ", "to learn more about referrals": "to learn more about referrals", - "Woah, you have a lot of friends! You've claimed the maximum amount of referral rewards. Check back soon to see if more are available!.": "Woah, you have a lot of friends! You've claimed the maximum amount of referral rewards. Check back soon to see if more are available!.", - "Invite History": "Invite History", - "Claim Your 150 LBC Invite Reward": "Claim Your 150 LBC Invite Reward", - "Invitee Email": "Invitee Email", - "Invite Status": "Invite Status", - "Reward": "Reward", - "Not Accepted": "Not Accepted", - "Unclaimable": "Unclaimable", - "Accepted": "Accepted", - "Claimed": "Claimed", - "Claimable": "Claimable", + "Power To The People": "Power To The People", + "LBRY is powered by the users. More users, more power… and with great power comes great responsibility.": "LBRY is powered by the users. More users, more power… and with great power comes great responsibility.", "Checking your invite status": "Checking your invite status", + "You have ...": "You have ...", + "You have no rewards available, please check": "You have no rewards available, please check", + "Don't Miss Out": "Don't Miss Out", + "We'll let you know about LBRY updates, security issues, and great new content.": "We'll let you know about LBRY updates, security issues, and great new content.", + "Your email address will never be sold and you can unsubscribe at any time.": "Your email address will never be sold and you can unsubscribe at any time.", + "View Rewards": "View Rewards", + "Latest From Your Subscriptions": "Latest From Your Subscriptions", + "Find New Channels": "Find New Channels", + "Discover New Channels": "Discover New Channels", + "View Your Subscriptions": "View Your Subscriptions", + "publishes": "publishes", + "About": "About", + "Share Channel": "Share Channel", + "This channel hasn't uploaded anything.": "This channel hasn't uploaded anything.", + "Go to page:": "Go to page:", + "Nothing here yet": "Nothing here yet", + "Enter a URL for your thumbnail.": "Enter a URL for your thumbnail.", + "Thumbnail Preview": "Thumbnail Preview", + "Use thumbnail upload tool": "Use thumbnail upload tool", + "Create a URL for this content. Simpler names are easier to find and remember.": "Create a URL for this content. Simpler names are easier to find and remember.", + "Subscribed": "Subscribed", + "Open file": "Open file", + "Delete this file": "Delete this file", + "Delete": "Delete", + "Downloaded to": "Downloaded to", + "You have...": "You have...", "Balance": "Balance", "You currently have": "You currently have", - "LBC": "LBC", - "You have": "You have", - "in unclaimed rewards": "in unclaimed rewards", - "Claim Rewards": "Claim Rewards", - "to learn more about LBRY Rewards": "to learn more about LBRY Rewards", "Recent Transactions": "Recent Transactions", - "No transactions... yet.": "No transactions... yet.", - "Refresh": "Refresh", - "Loading transactions": "Loading transactions", "Looks like you don't have any recent transactions.": "Looks like you don't have any recent transactions.", "Full History": "Full History", + "Refresh": "Refresh", + "Send Credits": "Send Credits", + "Send LBC to your friends or favorite creators": "Send LBC to your friends or favorite creators", "Amount": "Amount", + "Recipient address": "Recipient address", + "Send": "Send", + "Receive Credits": "Receive Credits", + "Use this wallet address to receive credits sent by another user (or yourself).": "Use this wallet address to receive credits sent by another user (or yourself).", + "Address copied.": "Address copied.", + "Get New Address": "Get New Address", + "Show QR code": "Show QR code", + "You can generate a new address at any time, and any previous addresses will continue to work. Using multiple addresses can be helpful for keeping track of incoming payments from multiple sources.": "You can generate a new address at any time, and any previous addresses will continue to work. Using multiple addresses can be helpful for keeping track of incoming payments from multiple sources.", "Type": "Type", "Details": "Details", "Transaction": "Transaction", "Date": "Date", - "Unlock Tip": "Unlock Tip", + "Abandon Claim": "Abandon Claim", + "fee": "fee", + "Find New Tags To Follow": "Find New Tags To Follow", + "Aw shucks!": "Aw shucks!", + "There was an error. It's been reported and will be fixed": "There was an error. It's been reported and will be fixed", + "Try": "Try", + "refreshing the app": "refreshing the app", + "to fix it": "to fix it", + "Search": "Search", + "Starting up": "Starting up", + "Connecting": "Connecting", + "It looks like you deleted or moved this file. We're rebuilding it now. It will only take a few seconds.": "It looks like you deleted or moved this file. We're rebuilding it now. It will only take a few seconds.", + "Newest First": "Newest First", + "Oldest First": "Oldest First", + "Contact": "Contact", + "Site": "Site", + "Send a tip to": "Send a tip to", + "This will appear as a tip for \"Why I Quit YouTube\".": "This will appear as a tip for \"Why I Quit YouTube\".", + "You sent 10 LBC as a tip, Mahalo!": "You sent 10 LBC as a tip, Mahalo!", + "History": "History", + "/wallet": "/wallet", + "Pending": "Pending", + "You have %s in unclaimed rewards.": "You have %s in unclaimed rewards.", "Download Directory": "Download Directory", "LBRY downloads will be saved here.": "LBRY downloads will be saved here.", "Max Purchase Price": "Max Purchase Price", @@ -104,178 +216,36 @@ "Encrypt my wallet with a custom password.": "Encrypt my wallet with a custom password.", "Secure your local wallet data with a custom password.": "Secure your local wallet data with a custom password.", "Lost passwords cannot be recovered.": "Lost passwords cannot be recovered.", - "Learn more": "Learn more", "Experimental Settings": "Experimental Settings", "Automatically download new content from my subscriptions": "Automatically download new content from my subscriptions", "The latest file from each of your subscriptions will be downloaded for quick access as soon as it's published.": "The latest file from each of your subscriptions will be downloaded for quick access as soon as it's published.", "Autoplay media files": "Autoplay media files", "Autoplay video and audio files when navigating to a file, as well as the next related item when a file finishes playing.": "Autoplay video and audio files when navigating to a file, as well as the next related item when a file finishes playing.", + "Multi-language support is brand new and incomplete. Switching your language may have unintended consequences.": "Multi-language support is brand new and incomplete. Switching your language may have unintended consequences.", "Application Cache": "Application Cache", "This will clear the application cache. Your wallet will not be affected.": "This will clear the application cache. Your wallet will not be affected.", "Clear Cache": "Clear Cache", "Choose Directory": "Choose Directory", - "Price": "Price", "Currency": "Currency", "LBRY Credits (LBC)": "LBRY Credits (LBC)", "US Dollars": "US Dollars", - "Blockchain Sync": "Blockchain Sync", - "Catching up with the blockchain": "Catching up with the blockchain", - "Uh oh. Sean must have messed something up. Try refreshing to fix it.": "Uh oh. Sean must have messed something up. Try refreshing to fix it.", - "If you still have issues, your anti-virus software or firewall may be preventing startup.": "If you still have issues, your anti-virus software or firewall may be preventing startup.", - "Reach out to hello@lbry.com for help, or check out": "Reach out to hello@lbry.com for help, or check out", - "Account": "Account", - "Make This Your Own": "Make This Your Own", - "You are already following a couple tags, try searching for a new one.": "You are already following a couple tags, try searching for a new one.", - "Tags": "Tags", - "Home": "Home", - "Aw shucks!": "Aw shucks!", - "There was an error. It's been reported and will be fixed": "There was an error. It's been reported and will be fixed", - "Try": "Try", - "refreshing the app": "refreshing the app", - "to fix it": "to fix it", - "NEW": "NEW", - "The publisher has chosen to charge LBC to view this content. Your balance is currently to low to view it.": "The publisher has chosen to charge LBC to view this content. Your balance is currently to low to view it.", - "Checkout": "Checkout", - "the rewards page": "the rewards page", - "or send more LBC to your wallet.": "or send more LBC to your wallet.", - "Published on": "Published on", - "Send a tip": "Send a tip", - "Share": "Share", - "Play": "Play", - "Report content": "Report content", - "Content-Type": "Content-Type", - "Languages": "Languages", - "License": "License", - "Want to comment?": "Want to comment?", - "More": "More", - "Download": "Download", - "Content": "Content", - "What are you publishing?": "What are you publishing?", - "to learn more.": "to learn more.", - "Title": "Title", - "Titular Title": "Titular Title", - "Description": "Description", - "Description of your content": "Description of your content", - "Thumbnail": "Thumbnail", - "Enter a URL for your thumbnail.": "Enter a URL for your thumbnail.", - "How much will this content cost?": "How much will this content cost?", - "Free": "Free", - "Choose price": "Choose price", - "Anonymous or under a channel?": "Anonymous or under a channel?", - "This is a username or handle that your content can be found under.": "This is a username or handle that your content can be found under.", - "Ex. @Marvel, @TheBeatles, @BooksByJoe": "Ex. @Marvel, @TheBeatles, @BooksByJoe", - "Where can people find this content?": "Where can people find this content?", - "The LBRY URL is the exact address where people find your content (ex. lbry://myvideo).": "The LBRY URL is the exact address where people find your content (ex. lbry://myvideo).", - "Name": "Name", - "Deposit (LBC)": "Deposit (LBC)", - "Mature audiences only": "Mature audiences only", - "Language": "Language", - "English": "English", - "Chinese": "Chinese", - "French": "French", - "German": "German", - "Japanese": "Japanese", - "Russian": "Russian", - "Spanish": "Spanish", - "Indonesian": "Indonesian", - "Italian": "Italian", - "Dutch": "Dutch", - "Turkish": "Turkish", - "Polish": "Polish", - "Malay": "Malay", - "By continuing, you accept the": "By continuing, you accept the", - "LBRY Terms of Service": "LBRY Terms of Service", - "Choose File": "Choose File", - "No File Chosen": "No File Chosen", - "Thumbnail Preview": "Thumbnail Preview", - "Use thumbnail upload tool": "Use thumbnail upload tool", - "Anonymous": "Anonymous", - "New channel...": "New channel...", - "Create a URL for this content. Simpler names are easier to find and remember.": "Create a URL for this content. Simpler names are easier to find and remember.", - "Any amount will give you the winning bid.": "Any amount will give you the winning bid.", - "This LBC remains yours and the deposit can be undone at any time.": "This LBC remains yours and the deposit can be undone at any time.", - "License (Optional)": "License (Optional)", - "None": "None", - "Public Domain": "Public Domain", - "Copyrighted...": "Copyrighted...", - "Other...": "Other...", - "Upload your thumbnail (.png/.jpg/.jpeg/.gif) to": "Upload your thumbnail (.png/.jpg/.jpeg/.gif) to", - "spee.ch": "spee.ch", - "Recommended size: 800x450 (16:9)": "Recommended size: 800x450 (16:9)", - "Choose Thumbnail": "Choose Thumbnail", - "Enter a thumbnail URL": "Enter a thumbnail URL", - "Receive Credits": "Receive Credits", - "Use this wallet address to receive credits sent by another user (or yourself).": "Use this wallet address to receive credits sent by another user (or yourself).", - "Address copied.": "Address copied.", - "Get New Address": "Get New Address", - "Show QR code": "Show QR code", - "You can generate a new address at any time, and any previous addresses will continue to work. Using multiple addresses can be helpful for keeping track of incoming payments from multiple sources.": "You can generate a new address at any time, and any previous addresses will continue to work. Using multiple addresses can be helpful for keeping track of incoming payments from multiple sources.", - "Send Credits": "Send Credits", - "Send LBC to your friends or favorite creators": "Send LBC to your friends or favorite creators", - "Recipient address": "Recipient address", - "Send": "Send", - "No transactions.": "No transactions.", - "FREE": "FREE", - "Search": "Search", - "Invalid character %s in name: %s.": "Invalid character %s in name: %s.", - "View file": "View file", "There's nothing available at this location.": "There's nothing available at this location.", "Loading decentralized data...": "Loading decentralized data...", - "See All Visited Links": "See All Visited Links", - "Open file": "Open file", - "Delete this file": "Delete this file", - "Delete": "Delete", - "Downloaded to": "Downloaded to", - "Drop to remove": "Drop to remove", - "About": "About", - "Share Channel": "Share Channel", - "Newest First": "Newest First", - "Oldest First": "Oldest First", - "Go to page:": "Go to page:", - "Nothing here yet": "Nothing here yet", - "Claim sequence must be a number.": "Claim sequence must be a number.", - "Requesting stream...": "Requesting stream...", - "Connecting...": "Connecting...", - "Confirm Purchase": "Confirm Purchase", - "This will purchase": "This will purchase", - "for": "for", - "credits": "credits", - "Downloading stream... not long left now!": "Downloading stream... not long left now!", - "Downloading: ": "Downloading: ", - "% complete": "% complete", - "Waiting for blob.": "Waiting for blob.", - "Waiting for metadata.": "Waiting for metadata.", - "Sorry, looks like we can't play this file.": "Sorry, looks like we can't play this file.", - "Sorry, looks like we can't preview this file.": "Sorry, looks like we can't preview this file.", - "files": "files", - "hidden due to your": "hidden due to your", - "content viewing preferences": "content viewing preferences", + "Confirm File Remove": "Confirm File Remove", + "Remove": "Remove", + "Are you sure you'd like to remove": "Are you sure you'd like to remove", + "from the LBRY app?": "from the LBRY app?", + "Also delete this file from my computer": "Also delete this file from my computer", "Less": "Less", - "Find New Channels": "Find New Channels", - "Latest From Your Subscriptions": "Latest From Your Subscriptions", - "publishes": "publishes", - "No modifier provided after separator %s.": "No modifier provided after separator %s.", - "View Your Subscriptions": "View Your Subscriptions", - "You might like these channels": "You might like these channels", - "This channel hasn't uploaded anything.": "This channel hasn't uploaded anything.", - "Web link": "Web link", - "Facebook": "Facebook", - "": "", - "Twitter": "Twitter", - "View on Spee.ch": "View on Spee.ch", - "LBRY App link": "LBRY App link", - "Done": "Done", - "fee": "fee", + "Warning!": "Warning!", + "Confirm External Resource": "Confirm External Resource", + "Continue": "Continue", + "This file has been shared with you by other people.": "This file has been shared with you by other people.", + "LBRY Inc is not responsible for its content, click continue to proceed at your own risk.": "LBRY Inc is not responsible for its content, click continue to proceed at your own risk.", "Find what you were looking for?": "Find what you were looking for?", "Yes": "Yes", "No": "No", "These search results are provided by LBRY, Inc.": "These search results are provided by LBRY, Inc.", "FILTER": "FILTER", - "View": "View", - "No results": "No results", - "Following": "Following", - "Uh oh. The flux in our Retro Encabulator must be out of whack. Try refreshing to fix it.": "Uh oh. The flux in our Retro Encabulator must be out of whack. Try refreshing to fix it.", - "Failed to load settings.": "Failed to load settings.", - "Multi-language support is brand new. Switching your language may have unintended consequences. Email ": "Multi-language support is brand new. Switching your language may have unintended consequences. Email ", - "Multi-language support is brand new and incomplete. Switching your language may have unintended consequences.": "Multi-language support is brand new and incomplete. Switching your language may have unintended consequences." + "View file": "View file" } \ No newline at end of file diff --git a/static/locales/pl.json b/static/locales/pl.json index d00674e60..617233669 100644 --- a/static/locales/pl.json +++ b/static/locales/pl.json @@ -283,5 +283,8 @@ "Open file": "Otwórz plik", "NEW": "NEW", "Failed to load settings.": "Failed to load settings.", - "Multi-language support is brand new and incomplete. Switching your language may have unintended consequences.": "Multi-language support is brand new and incomplete. Switching your language may have unintended consequences." + "Multi-language support is brand new and incomplete. Switching your language may have unintended consequences.": "Multi-language support is brand new and incomplete. Switching your language may have unintended consequences.", + "Wallet": "Wallet", + "Home": "Home", + "Following": "Following" } \ No newline at end of file diff --git a/yarn.lock b/yarn.lock index 4763077c4..d787eca78 100644 --- a/yarn.lock +++ b/yarn.lock @@ -909,22 +909,41 @@ resolved "https://registry.yarnpkg.com/@posthtml/esm/-/esm-1.0.0.tgz#09bcb28a02438dcee22ad1970ca1d85a000ae0cf" integrity sha512-dEVG+ITnvqKGa4v040tP+n8LOKOqr94qjLva7bE5pnfm2KHJwsKz69J4KMxgWLznbpBJzy8vQfCayEk3vLZnZQ== -"@reach/auto-id@^0.2.0": +"@reach/auto-id@0.2.0", "@reach/auto-id@^0.2.0": version "0.2.0" resolved "https://registry.yarnpkg.com/@reach/auto-id/-/auto-id-0.2.0.tgz#97f9e48fe736aa5c6f4f32cf73c1f19d005f8550" integrity sha512-lVK/svL2HuQdp7jgvlrLkFsUx50Az9chAhxpiPwBqcS83I2pVWvXp98FOcSCCJCV++l115QmzHhFd+ycw1zLBg== -"@reach/component-component@^0.1.3": +"@reach/component-component@0.1.3", "@reach/component-component@^0.1.3": version "0.1.3" resolved "https://registry.yarnpkg.com/@reach/component-component/-/component-component-0.1.3.tgz#5d156319572dc38995b246f81878bc2577c517e5" integrity sha512-a1USH7L3bEfDdPN4iNZGvMEFuBfkdG+QNybeyDv8RloVFgZYRoM+KGXyy2KOfEnTUM8QWDRSROwaL3+ts5Angg== +"@reach/menu-button@^0.1.18": + version "0.1.18" + resolved "https://registry.yarnpkg.com/@reach/menu-button/-/menu-button-0.1.18.tgz#cb9e3bf1c2a2bdb5d618697b87ad353dfbca123e" + integrity sha512-MGdN8SWaQ0u0xj6KWUnK9fFc1VBg8NhNnFhEd2sp3D56XJcr08HU5GeVq/MFf5C97mxRnIPIKGnMPPeGAn9OFA== + dependencies: + "@reach/component-component" "0.1.3" + "@reach/portal" "^0.2.1" + "@reach/rect" "0.2.1" + "@reach/utils" "^0.2.3" + "@reach/window-size" "^0.1.4" + warning "^4.0.2" + "@reach/observe-rect@^1.0.3": version "1.0.3" resolved "https://registry.yarnpkg.com/@reach/observe-rect/-/observe-rect-1.0.3.tgz#2ea3dcc369ab22bd9f050a92ea319321356a61e8" integrity sha1-LqPcw2mrIr2fBQqS6jGTITVqYeg= -"@reach/rect@^0.2.1": +"@reach/portal@^0.2.1": + version "0.2.1" + resolved "https://registry.yarnpkg.com/@reach/portal/-/portal-0.2.1.tgz#07720b999e0063a9e179c14dbdc60fd991cfc9fa" + integrity sha512-pUQ0EtCcYm4ormEjJmdk4uzZCxOpaRHB8FDKJXy6q6GqRqQwZ4lAT1f2Tvw0DAmULmyZTpe1/heXY27Tdnct+Q== + dependencies: + "@reach/component-component" "^0.1.3" + +"@reach/rect@0.2.1", "@reach/rect@^0.2.1": version "0.2.1" resolved "https://registry.yarnpkg.com/@reach/rect/-/rect-0.2.1.tgz#7343020174c90e2290b844d17c03fd9c78e6b601" integrity sha512-aZ9RsNHDMQ3zETonikqu9/85iXxj+LPqZ9Gr9UAncj3AufYmGeWG3XG6b37B+7ORH+mkhVpLU2ZlIWxmOe9Cqg== @@ -941,11 +960,40 @@ "@reach/utils" "^0.2.2" warning "^4.0.2" +"@reach/tooltip@^0.2.1": + version "0.2.1" + resolved "https://registry.yarnpkg.com/@reach/tooltip/-/tooltip-0.2.1.tgz#70a80d6defedee53cedf5480cd3d37dfb20020d0" + integrity sha512-3O7oXoymNkEAolHN9WbuspY7mA3zIOrTaibmYkKFtGT6FgyBrAQyOQn1ZhBuSza6RjSIkEtFRpbDEKK1UJEI6A== + dependencies: + "@reach/auto-id" "0.2.0" + "@reach/portal" "^0.2.1" + "@reach/rect" "^0.2.1" + "@reach/utils" "^0.2.3" + "@reach/visually-hidden" "^0.1.4" + prop-types "^15.7.2" + "@reach/utils@^0.2.2": version "0.2.2" resolved "https://registry.yarnpkg.com/@reach/utils/-/utils-0.2.2.tgz#c3a05ae9fd1f921988ae8a89b5a0d28d1a2b92df" integrity sha512-jYeIi46AA5jh2gfdXD/nInUYfeLp3girRafiajP7AVHF6B4hpYAzUSx/ZH4xmPyf5alut5rml2DHxrv+X+Xu+A== +"@reach/utils@^0.2.3": + version "0.2.3" + resolved "https://registry.yarnpkg.com/@reach/utils/-/utils-0.2.3.tgz#820f6a6af4301b4c5065cfc04bb89e6a3d1d723f" + integrity sha512-zM9rA8jDchr05giMhL95dPeYkK67cBQnIhCVrOKKqgWGsv+2GE/HZqeptvU4zqs0BvIqsThwov+YxVNVh5csTQ== + +"@reach/visually-hidden@^0.1.4": + version "0.1.4" + resolved "https://registry.yarnpkg.com/@reach/visually-hidden/-/visually-hidden-0.1.4.tgz#0dc4ecedf523004337214187db70a46183bd945b" + integrity sha512-QHbzXjflSlCvDd6vJwdwx16mSB+vUCCQMiU/wK/CgVNPibtpEiIbisyxkpZc55DyDFNUIqP91rSUsNae+ogGDQ== + +"@reach/window-size@^0.1.4": + version "0.1.4" + resolved "https://registry.yarnpkg.com/@reach/window-size/-/window-size-0.1.4.tgz#3257b646548f61c2708a661a683620fbe0a706cb" + integrity sha512-JZshEuGsLvi6fUIJ7Unx12yNeM5SmqWjber2MLr9tfwf1hpNv73EiPBOIJyV0DjW7GXzjcOEvwnqysm59s2s/A== + dependencies: + "@reach/component-component" "^0.1.3" + "@samverschueren/stream-to-observable@^0.3.0": version "0.3.0" resolved "https://registry.yarnpkg.com/@samverschueren/stream-to-observable/-/stream-to-observable-0.3.0.tgz#ecdf48d532c58ea477acfcab80348424f8d0662f" @@ -6588,9 +6636,9 @@ lazy-val@^1.0.3, lazy-val@^1.0.4: yargs "^13.2.2" zstd-codec "^0.1.1" -lbry-redux@lbryio/lbry-redux#291324d03f694c4fefa6967aa7be02d9245596a8: +lbry-redux@lbryio/lbry-redux#6a447d0542d23b9a37e266f5f85d3bde5297a451: version "0.0.1" - resolved "https://codeload.github.com/lbryio/lbry-redux/tar.gz/291324d03f694c4fefa6967aa7be02d9245596a8" + resolved "https://codeload.github.com/lbryio/lbry-redux/tar.gz/6a447d0542d23b9a37e266f5f85d3bde5297a451" dependencies: proxy-polyfill "0.1.6" reselect "^3.0.0"